Jackson
是当前用的比较广泛的,用来序列化和反序列化Json
的 Java 的开源框架。Spring MVC
默认采用Jackson
解析Json
,出于最小依赖的考虑,也许Json
解析第一选择就应该是Jackson
。
一、简介
Jackson 优点很多。
- Jackson 所依赖的 jar 包较少 ,简单易用。
- Jackson 解析大的 json 文件速度比较快;Jackson 运行时占用内存比较低,性能比较好;
- Jackson 有灵活的 API,可以很容易进行扩展和定制。
Jackson 的 1.x
版本的包名是 org.codehaus.jackson
,当升级到 2.x
版本时,包名变为 com.fasterxml.jackson
。
Jackson 的核心模块由三部分组成。
-
jackson-core:核心包,定义了低层次的
streaming API
,包含了 JSON 的特定实现。 - jackson-annotations :注解包,包含标准的 Jackson 注解。
-
jackson-databind :数据绑定包, 提供基于 对象绑定 解析的相关 API (
ObjectMapper
) 和 树模型 解析的相关 API (JsonNode
)。
二、依赖
jackson-databind
依赖jackson-core
和jackson-annotations
。
使用 Maven 构建项目,可以只显示地添加 jackson-databind
依赖,jackson-core
和 jackson-annotations
也会通过 Maven 传递性依赖 随之添加到 Java 项目工程中。
com.fasterxml.jackson.corejackson-databind2.12.2
三、 ObjectMapper
Jackson 最常用的 API 就是基于 对象绑定 的 ObjectMapper
:
-
ObjectMapper
可以从字符串,流或文件中解析JSON
,并创建表示已解析的JSON
的Java
对象。 -
ObjectMapper
也可以从Java
对象创建JSON
。 -
ObjectMapper
可以将JSON
解析为自定义的类的对象,也可以解析置JSON 树模型
的对象。
之所以称为 ObjectMapper
是因为它将 JSON
映射到 Java 对象(反序列化),或者将 Java 对象映射到 JSON
(序列化)。
POJO 的序列化和反序列化
参考:https://github.com/FasterXML/jackson-databind#1-minute-tutorial-pojos-to-json-and-back
开始之前先准备一个拥有两个属性的 POJO
。
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Person {
private String name;
private int age;
public static Person from(String name, int age) {
return new Person(name, age);
}
}
案例:
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class JacksonDemo {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
Person zhangsan = Person.from("zhangsan", 18);
String serializer = mapper.writeValueAsString(zhangsan);
Person deserializer = mapper.readValue(serializer, Person.class);
System.out.println(serializer); // {"name":"zhangsan","age":18}
System.out.println(deserializer); // Person(name=zhangsan, age=18)
}
}
其他序列化 API:
// 序列化到一个字节数组
public byte[] writeValueAsBytes(Object value);
// 序列化到一个文件中
public void writeValue(File resultFile, Object value);
其他反序列化 API:
// 从文件中读取 JSON 数据
public T readValue(File src, Class valueType);
// 从一个 URL 中读取 JSON 数据
public T readValue(URL src, Class valueType)
序列化时忽略字段
方式一:使用 @JsonIgnore
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.IOException;
public class JacksonFilterDemo {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
IgnoreAgePerson zhangsan = IgnoreAgePerson.from("zhangsan", 18);
String serializer = mapper.writeValueAsString(zhangsan);
System.out.println(serializer); // {"name":"zhangsan"}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
static class IgnoreAgePerson {
private String name;
@JsonIgnore
private int age;
public static IgnoreAgePerson from(String name, int age) {
return new IgnoreAgePerson(name, age);
}
}
}
方式二:使用 Filter
动态过滤字段
先实现一个工具类 JsonFilterUtil
。
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
public class JsonFilterUtil {
public static String serialize(Object object, String... excludeProperties) {
ObjectMapper mapper = new ObjectMapper();
addFilterForMapper(mapper, object.getClass(), excludeProperties);
try {
return mapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
/**
* 添加过滤的字段
*/
private static void addFilterForMapper(ObjectMapper mapper, Class filterClass, String... excludeProperties) {
SimpleBeanPropertyFilter fieldFilter = SimpleBeanPropertyFilter.serializeAllExcept(excludeProperties);
SimpleFilterProvider filterProvider = new SimpleFilterProvider().addFilter("fieldFilter", fieldFilter);
mapper.setFilterProvider(filterProvider).addMixIn(filterClass, FieldFilterMixIn.class);
}
/**
* 定义一个类或接口
*/
@JsonFilter("fieldFilter")
interface FieldFilterMixIn{
}
}
使用 Demo:
public class JacksonFilterDemo {
public static void main(String[] args) {
Person zhangsan = Person.from("zhangsan", 18);
System.out.println(JsonFilterUtil.serialize(zhangsan)); // {"name":"zhangsan","age":18}
System.out.println(JsonFilterUtil.serialize(zhangsan, "name")); // {"age":18}
System.out.println(JsonFilterUtil.serialize(zhangsan, "age")); // {"name":"zhangsan"}
System.out.println(JsonFilterUtil.serialize(zhangsan, "name", "age")); // {}
}
}
参考
- Jackson用法详解
- https://github.com/FasterXML/jackson-docs
- https://www.baeldung.com/jackson-ignore-properties-on-serialization#filters
- Jackson实现动态过滤