起源
当后端接口向前端返回数据时,有时response数据是null, 十分不利于前端处理。
因此为了统一格式,需要返回在:
- 接口返回得数据是String类型时,不返回null,而返回 “”
- 接口返回得数据是Map类型时,不返回null,而返回 {}
- 接口返回得数据是List类型时,不返回null,而返回 []
为了解决这个问题,就到了选择json序列化工具得时候,目前有三种工具:
- fastjson 是阿里巴巴2011年的开源 json 解析库
- jackjson 是 spring boot 官方内置得 json 解析库
- Gson 是 Google 官方2008年开源得 json 解析库
如何选择?
选择 jackson.( 2.13.0+版本)速度与性能安全,功能完善适中得选项。
如何使用?
添加坐标
<properties>
......
<jackson.version>2.13.2</jackson.version>
......
</properties>
</dependencies>
...
<!-- json序列化 工具类 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
...
</dependencies>
全局配置文件:JacksonConfig.java
package com.springblog.config;
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 org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Collection;
/**
* <p>
* json序列化
* </p>
*
* @author ifredom@gmail.com
* @since 2022-05-09
*/
@Configuration
public class JacksonConfig {
@Bean
@Primary
@ConditionalOnMissingBean(ObjectMapper.class)
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
@Override
public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
String fieldName = jsonGenerator.getOutputContext().getCurrentName();
try {
Field field = jsonGenerator.getCurrentValue().getClass().getDeclaredField(fieldName);
if (CharSequence.class.isAssignableFrom(field.getType())) {
// 字符串空值 “”
jsonGenerator.writeString("");
} else if (Collection.class.isAssignableFrom(field.getType())) {
//列表型空值返回[]
jsonGenerator.writeStartArray();
jsonGenerator.writeEndArray();
} else {
//map类型空值,或者bean对像,返回{}
jsonGenerator.writeStartObject();
jsonGenerator.writeEndObject();
}
} catch (NoSuchFieldException ignoredException) {
// 忽略该异常
}
}
});
return objectMapper;
}
}
原理讲解
jackson有三个核心模块,如下,括号内是maven的artifactId:
- Stre
- aming(jackson-core):低阶API库,提供流式解析工具JsonParser,流式生成工具JsonGenerator;
- Annotations(jackson-annotations):jackson注解;
- Databind (jackson-databind):基于java对象的序列化、反序列化能力,需要前面两个模块的支持才能实现;
当我们用jackson做JSON操作时,常用的是 Databind 模块 的 ObjectMapper 类,对处于核心位置的jackson-core反倒是很少直接用到,那么该模块有什么作用呢?
在 jackson-core
中,有一个叫做 BeanSerializer
的功能类,其 serialize
方法负责 将java对象转为JSON字符串,方法中的处理逻辑就是调用JsonGenerator提供的API,而JsonGenerator就是jackson-core中负责序列化的主要功能类
日常使用序列化功能
- 将JSON转换为Java对象
- 将json字符串序列化为Java对象
public void jsonDemo() {
String jsonString = "{ \"title\" : \"json博客标题\", \"description\" : \"json文章描述\" }";
ObjectMapper objectMapper = new ObjectMapper();
try {
BlogEntity blog = objectMapper.readValue(jsonString, BlogEntity.class);
System.out.println("car brand = " + blog.getTitle());
System.out.println("car doors = " + blog.getDescription());
} catch (IOException e) {
e.printStackTrace();
}
}
jackjson支持从各种类型数据中进行序列化为java对象,支持类型如下:
- json字符串
ObjectMapper objectMapper = new ObjectMapper();
String json =
"{ \"title\" : \"标题\", \"description\" :\"描述\" }";
Car car = objectMapper.readValue(json, BlogEntity.class);
- 文件file
ObjectMapper objectMapper = new ObjectMapper();
File file = new File("data/blog.json");
BlogEntity blog = objectMapper.readValue(file, BlogEntity.class);
- 字符输入流StringReader
ObjectMapper objectMapper = new ObjectMapper();
String json =
"{ \"title\" : \"标题\", \"description\" :\"描述\" }";
Reader reader = new StringReader( json);
BlogEntity blog = objectMapper.readValue(file, BlogEntity.class);
- JSON via URL
ObjectMapper objectMapper = new ObjectMapper();
URL url = new URL("file:data/blog.json");
BlogEntity blog = objectMapper.readValue(url, BlogEntity.class);
- 字节输入流FileInputStream
ObjectMapper objectMapper = new ObjectMapper();
InputStream input = new FileInputStream("data/blog.json");
BlogEntity blog = objectMapper.readValue(input , BlogEntity.class);
- 字节数组 List<Bytes>
ObjectMapper objectMapper = new ObjectMapper();
byte[] bytes =
"{ \"title\" : \"标题\", \"description\" : \“描述\” }".getBytes("UTF-8");
BlogEntity blog = objectMapper.readValue(bytes , BlogEntity.class);
- JSON数组字符串 :
ObjectMapper objectMapper = new ObjectMapper();
String jsonArray = "[{\"title\":\"标题\"}, {\"description\":\"描述\"}]"
// 转换为 Array
BlogEntity[] blogs = objectMapper.readValue(jsonArray , BlogEntity.class);
// 转换为List
List<BlogEntity> blogs2 = objectMapper.readValue(jsonArray, new TypeReference<List<BlogEntity>>(){});
- JSON字符串Map
ObjectMapper objectMapper = new ObjectMapper();
String jsonObject = "{\"brand\":\"ford\", \"doors\":5}";
Map<String, Object> jsonMap = objectMapper.readValue(jsonObject,
new TypeReference<Map<String,Object>>(){});
- 将java对象转换为json字符串
BlogEntity blogEntity = new BlogEntity();
blogEntity.setTitle("新博客");
blogEntity.setDescription("文章描述");
ObjectMapper objectMapper = new ObjectMapper();
String str = objectMapper.writeValueAsString(blogEntity);
System.out.println(str);
日常使用序列化注解
注解 | 用法 |
---|---|
@JsonProperty | 用于属性,把属性的名称序列化时转换为另外一个名称。示例: @JsonProperty(“birth_date”) private Date birthDate; |
@JsonFormat | 用于属性或者方法,把属性的格式序列化时转换成指定的格式。示例: @JsonFormat(timezone = “GMT+8”, pattern = “yyyy-MM-dd HH:mm”) ) public Date getBirthDate(){ } |
@JsonPropertyOrder | 用于类, 指定属性在序列化时 json 中的顺序 , 示例:) @JsonPropertyOrder({ “birth_Date”, “name” }) public class Person(){ } |
@JsonCreator | 用于构造方法,和 @JsonProperty 配合使用,适用有参数的构造方法。 示例: @JsonCreator public Person(@JsonProperty(“name”) String name) { … } |
@JsonAnySetter | 用于属性或者方法,设置未反序列化的属性名和值作为键值存储到 map 中 ) @JsonAnySetter public void set(String key, Object,value) { map.put(key, value); } |
@JsonAnyGetter | 用于方法 ,获取所有未序列化的属性 public Map<String, Object> any() { return map; } |
参考资料
jackjson官方文档
jackjson方法细节
自定义解析
------ 如果文章对你有用,感谢 >>>点赞 | 收藏 <<<