我在Sping Boot 应用程序(版本2.7.13)中返回带有转义字符的JSON时遇到了问题。
下面示例代码中的/demo
端点:
package com.example.invalidjson.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@RestController
@RequestMapping("/")
public class DemoController {
@GetMapping(path = "/demo")
Demo getExample() {
Demo demo = new Demo();
demo.setTitle("Example of \n JSON");
return demo;
}
@GetMapping(path = "/read")
void readExample() {
try {
ObjectMapper objectMapper = new ObjectMapper();
Demo demo = objectMapper.readValue("{\"title\" : \"Example of \n JSON\"}", Demo.class);
System.out.println("Reading succeeded: " + demo.getTitle());
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}
public static class Demo {
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
}
字符串
返回以下JSON:
{"title":"Example of \n JSON"}
型
问题是这个JSON不能被其他客户端解析。Jackson也没有读过。/read
端点引发以下异常:
com.fasterxml.jackson.core.JsonParseException: Illegal unquoted character ((CTRL-CHAR, code 10)): has to be escaped using backslash to be included in string value
at [Source: (String)"{"title" : "Example of
JSON"}"; line: 1, column: 25]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:2391) ~[jackson-core-2.13.5.jar:2.13.5]
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:735) ~[jackson-core-2.13.5.jar:2.13.5]
at com.fasterxml.jackson.core.base.ParserBase._throwUnquotedSpace(ParserBase.java:1110) ~[jackson-core-2.13.5.jar:2.13.5]
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._finishString2(ReaderBasedJsonParser.java:2155) ~[jackson-core-2.13.5.jar:2.13.5]
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._finishString(ReaderBasedJsonParser.java:2126) ~[jackson-core-2.13.5.jar:2.13.5]
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.getText(ReaderBasedJsonParser.java:320) ~[jackson-core-2.13.5.jar:2.13.5]
at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:41) ~[jackson-databind-2.13.5.jar:2.13.5]
at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:11) ~[jackson-databind-2.13.5.jar:2.13.5]
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129) ~[jackson-databind-2.13.5.jar:2.13.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:314) ~[jackson-databind-2.13.5.jar:2.13.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177) ~[jackson-databind-2.13.5.jar:2.13.5]
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323) ~[jackson-databind-2.13.5.jar:2.13.5]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4674) ~[jackson-databind-2.13.5.jar:2.13.5]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3629) ~[jackson-databind-2.13.5.jar:2.13.5]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3597) ~[jackson-databind-2.13.5.jar:2.13.5]
at com.example.invalidjson.demo.DemoApplication$DemoController.readExample(DemoApplication.java:34) ~[classes/:na]
...
型
我的理解是,Jackson作为Sping Boot 的默认JSON解析器,会自动转义像\n
和\t
这样的字符,或者我没有很好地理解文档。
我看到了一些使用JacksonConfiguration
的选项,比如:
package com.example.invalidjson.demo;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;
@Configuration
public class JacksonConfiguration {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
JsonSerializer<String> stringJsonSerializer = new JsonSerializer<String>() {
@Override
public void serialize(String value, JsonGenerator generator, SerializerProvider serializers) throws IOException {
generator.writeString(value.replace("\n", "\\n"));
}
};
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(String.class, stringJsonSerializer);
objectMapper.registerModule(simpleModule);
return objectMapper;
}
}
型
就没有别的办法处理吗?
根本的问题是:为什么Jackson会生成一个连自己都无法读取的JSON?
1条答案
按热度按时间aiazj4mn1#
要使用Sping Boot 和Jackson在默认情况下转义JSON响应中的\n和\t等字符,您可以配置Jackson使用的ObjectMapper以启用JsonGenerator.Feature.ESCAPE_NON_ASCII功能。此功能使用Unicode转义序列转义非ASCII字符,其中包括\n和\t等字符。
以下是您的操作方法:
创建配置类以自定义JacksonObjectMapper:
导入com.fasterxml.Jackson.core.JsonGenerator;导入com.fasterxml.Jackson.databind.ObjectMapper; import org.springframework.boot.autocigure.jackson.Jackson2ObjectMapperBuilderCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
public class MyClass {
字符串
}
在上面的配置类中,我们为Jackson 2 ObjectMapperBuilderCustomizer定义了一个bean,它启用了JsonGenerator.Feature.ESCAPE_NON_ASCII特性。
我们还为ObjectMapper本身定义了一个bean,在这里我们应用定制器来配置ObjectMapper示例。
有了上面的配置,Sping Boot 将使用定制的ObjectMapper来序列化JSON响应。\n和\t字符(沿着其他非ASCII字符)将使用Unicode转义序列进行转义。
注意:确保您已经在Sping Boot 项目中配置了Jackson依赖项。
就是这样!现在你的JSON响应应该默认包含转义字符,比如\n和\t。