原文连接👉 Jackson使用指南java
从事JAVA开发工做以来,一直都离不开Jackson的序列化反序列化,对于Jackson的使用也一直处于够用但不深刻的状态,下面是平常使用过程当中对Jackson的总结。node
像普通属性同样序列化Mapgit
public class ExtendableBean {
public String name;
private Map<String, String> properties;
@JsonAnyGetter
public Map<String, String> getProperties() {
return properties;
}
}
复制代码
序列化示例:github
{
"name":"My bean",
"attr2":"val2",
"attr1":"val1"
}
复制代码
将指定的方法标记为
getter
方法。能够用来代替@JsonProperty
json
public class MyBean {
public int id;
private String name;
@JsonGetter("name")
public String getTheName() {
return name;
}
}
复制代码
序列化示例:数组
{
"id": 1,
"name":"My bean"
}
复制代码
用在类上,在序列化的时候自定义属性输出顺序app
@JsonPropertyOrder({ "name", "id" })
public class MyBean {
public int id;
public String name;
}
复制代码
序列化示例:ide
{
"name":"My bean",
"id": 1
}
复制代码
彻底按照原样序列化属性的值函数
public class RawBean {
public String name;
@JsonRawValue
public String json;
}
复制代码
例如:jsonp
RawBean bean = new RawBean("My bean", "{\"attr\":false}");
复制代码
将序列化为:
{
"name":"My bean",
"json":{
"attr":false
}
}
复制代码
而不是:
{
"name":"My bean",
"json":"{\"attr\":false}"
}
复制代码
定义整个实体的序列化方法,Jackson将会使用该方法的输出做为序列化输出。
public enum TypeEnumWithValue {
TYPE1(1, "Type A"), TYPE2(2, "Type 2");
private Integer id;
private String name;
// standard constructors
@JsonValue
public String getName() {
return name;
}
}
复制代码
序列化示例:
{
"name": "Type 2"
}
复制代码
若是须要将实体包装一层,可使用
@JsonRootName
来指定根包装器的名称
@JsonRootName(value = "user")
public class UserWithRoot {
public int id;
public String name;
}
复制代码
序列化示例:
{
"user": {
"id": 1,
"name": "John"
}
}
复制代码
若是不用该注解,将会序列化为:
{
"id": 1,
"name": "John"
}
复制代码
用于指定自定义序列化器来序列化实体
public class Event {
public String name;
@JsonSerialize(using = CustomDateSerializer.class)
public Date eventDate;
}
复制代码
自定义序列化器以下:
public class CustomDateSerializer extends StdSerializer<Date> {
private static SimpleDateFormat formatter
= new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
public CustomDateSerializer() {
this(null);
}
public CustomDateSerializer(Class<Date> t) {
super(t);
}
@Override
public void serialize( Date value, JsonGenerator gen, SerializerProvider arg2) throws IOException, JsonProcessingException {
gen.writeString(formatter.format(value));
}
}
复制代码
输出示例:
{
"name": "test",
"eventDate": "20-12-2014 02:30:00"
}
复制代码
指定反序列化使用的构造函数或方法
待反序列化Json示例:
{
"id":1,
"theName":"My bean"
}
复制代码
public class BeanWithCreator {
public int id;
public String name;
@JsonCreator
public BeanWithCreator(@JsonProperty("id") int id, @JsonProperty("theName") String name) {
this.id = id;
this.name = name;
}
}
复制代码
指定某个字段从注入赋值,而不是从Json
public class BeanWithInject {
@JacksonInject
public int id;
public String name;
}
复制代码
示例用法:
String json = "{\"name\":\"My bean\"}";
InjectableValues inject = new InjectableValues.Std()
.addValue(int.class, 1);
BeanWithInject bean = new ObjectMapper().reader(inject)
.forType(BeanWithInject.class)
.readValue(json);
复制代码
在反序列化时,将Map当成普通属性
待反序列化Json:
{
"name":"My bean",
"attr2":"val2",
"attr1":"val1"
}
复制代码
public class ExtendableBean {
public String name;
private Map<String, String> properties;
@JsonAnySetter
public void add(String key, String value) {
properties.put(key, value);
}
}
复制代码
properties
字段的值将会是由 attr2 -> val2,attr1 -> val1
组成的键值对。
将方法标记为
setter
方法,能够指定属性名称
public class MyBean {
public int id;
private String name;
@JsonSetter("name")
public void setTheName(String name) {
this.name = name;
}
}
复制代码
用于指定自定义反序列化器来反序列化实体
public class Event {
public String name;
@JsonDeserialize(using = CustomDateDeserializer.class)
public Date eventDate;
}
复制代码
对应的反序列化器:
public class CustomDateDeserializer extends StdDeserializer<Date> {
private static SimpleDateFormat formatter
= new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
public CustomDateDeserializer() {
this(null);
}
public CustomDateDeserializer(Class<?> vc) {
super(vc);
}
@Override
public Date deserialize( JsonParser jsonparser, DeserializationContext context) throws IOException {
String date = jsonparser.getText();
try {
return formatter.parse(date);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
复制代码
在类上指定要忽略的属性
@JsonIgnoreProperties({ "id" })
public class BeanWithIgnore {
public int id;
public String name;
}
复制代码
在具体属性上忽略,使其不参与序列化过程
public class BeanWithIgnore {
@JsonIgnore
public int id;
public String name;
}
复制代码
与@JsonIgnoreProperties
是等效的。
用在类上,将忽略该类全部属性
public class User {
public int id;
public Name name;
@JsonIgnoreType
public static class Name {
public String firstName;
public String lastName;
}
}
复制代码
用于排除值为
empty/null/default
的属性
@JsonInclude(Include.NON_NULL)
public class MyBean {
public int id;
public String name;
}
复制代码
强制序列化私有属性,无论它有没有
getter
方法
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class PrivateBean {
private int id;
private String name;
}
复制代码
通常都是组合起来使用,有下面三个注解:
指定序列化中包含的类型信息的详细信息
指定带注释类型的子类型
指定用于带注释的类的逻辑类型名称
public class Zoo {
public Animal animal;
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Dog.class, name = "dog"),
@JsonSubTypes.Type(value = Cat.class, name = "cat")
})
public static class Animal {
public String name;
}
@JsonTypeName("dog")
public static class Dog extends Animal {
public double barkVolume;
}
@JsonTypeName("cat")
public static class Cat extends Animal {
boolean likesCream;
public int lives;
}
}
复制代码
上述例子中,指定属性type
为判断具体子类的依据,例如:type=dog
,将被序列化为Dog
类型。
指定JSON中的属性名称
public class MyBean {
public int id;
private String name;
@JsonProperty("name")
public void setTheName(String name) {
this.name = name;
}
@JsonProperty("name")
public String getTheName() {
return name;
}
}
复制代码
用于在序列化日期/时间值时指定格式。
public class Event {
public String name;
@JsonFormat(
shape = JsonFormat.Shape.STRING,
pattern = "dd-MM-yyyy hh:mm:ss")
public Date eventDate;
}
复制代码
将对象中全部的属性与当前平级,不太好描述,简单说就是拆开包装。
public class UnwrappedUser {
public int id;
@JsonUnwrapped
public Name name;
public static class Name {
public String firstName;
public String lastName;
}
}
复制代码
序列化示例:
{
"id":1,
"firstName":"John",
"lastName":"Doe"
}
复制代码
若是不加@JsonUnwrapped
注解,将被序列化为:
{
"id":1,
"name": {
"firstName":"John",
"lastName":"Doe"
}
}
复制代码
指定视图,相似分组进行序列化/反序列化
定义视图:
public class Views {
public static class Public {}
public static class Internal extends Public {}
}
复制代码
定义实体:
public class Item {
@JsonView(Views.Public.class)
public int id;
@JsonView(Views.Public.class)
public String itemName;
@JsonView(Views.Internal.class)
public String ownerName;
}
复制代码
序列化示例:
String result = new ObjectMapper()
.writerWithView(Views.Public.class)
.writeValueAsString(item);
复制代码
这时,将只会序列化id
和itemName
字段
@JsonManagedReference和@JsonBackReference注释用于处理父/子关系并解决循环问题。
例如,有两个相互引用的类:
public class ItemWithRef {
public int id;
public String itemName;
@JsonManagedReference
public UserWithRef owner;
}
复制代码
public class UserWithRef {
public int id;
public String name;
@JsonBackReference
public List<ItemWithRef> userItems;
}
复制代码
不加注解,会循环调用,致使内存溢出,这时候可使用@JsonManagedReference
和@JsonBackReference
来避免内存溢出。
用于指定在序列化/反序列化值时使用对象标识,例如,处理无限递归类型的问题。
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class ItemWithIdentity {
public int id;
public String itemName;
public UserWithIdentity owner;
}
复制代码
指定序列化期间要使用的过滤器。
@JsonFilter("myFilter")
public class BeanWithFilter {
public int id;
public String name;
}
复制代码
示例代码:
BeanWithFilter bean = new BeanWithFilter(1, "My bean");
FilterProvider filters
= new SimpleFilterProvider().addFilter(
"myFilter",
SimpleBeanPropertyFilter.filterOutAllExcept("name"));
String result = new ObjectMapper()
.writer(filters)
.writeValueAsString(bean);
复制代码
可使用@JacksonAnnotationsInside来开发自定义注解
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonInclude(Include.NON_NULL)
@JsonPropertyOrder({ "name", "id", "dateCreated" })
public @interface CustomAnnotation {}
复制代码
如何使用自定义注解:
@CustomAnnotation
public class BeanWithCustomAnnotation {
public int id;
public String name;
public Date dateCreated;
}
复制代码
自定义注解能够加强代码复用,把一些通用的Jackson注解组合起来,造成一个新注解,新注解能够代替组合的注解。
动态地为某些类型增长统一的Jackson注解
实体:
public class Item {
public int id;
public String itemName;
public User owner;
}
复制代码
MixIn类:
@JsonIgnoreType
public class MyMixInForIgnoreType {}
复制代码
咱们能够动态地让User
类型不参与序列化:
Item item = new Item(1, "book", null);
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(User.class, MyMixInForIgnoreType.class);
result = mapper.writeValueAsString(item);
复制代码
假设咱们有一个带Jackson注解的实体:
@JsonInclude(Include.NON_NULL)
@JsonPropertyOrder({ "name", "id" })
public class MyBean {
public int id;
public String name;
}
复制代码
咱们能够这样来禁用该实体上的全部Jackson注解:
MyBean bean = new MyBean(1, null);
ObjectMapper mapper = new ObjectMapper();
mapper.disable(MapperFeature.USE_ANNOTATIONS);
复制代码
ObjectMapper
用法能够直接序列化为Json字符串:
objectMapper.writeValueAsString(car);
复制代码
或者,能够序列化到文件,文件内容是Json字符串:
objectMapper.writeValue(new File("target/car.json"), car);
复制代码
从字符串:
String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
objectMapper.readValue(json, Car.class);
复制代码
从文件:
objectMapper.readValue(new File("target/json_car.json"), Car.class);
复制代码
从URL:
objectMapper.readValue(new URL("target/json_car.json"), Car.class);
复制代码
String json = "{ \"color\" : \"Black\", \"type\" : \"FIAT\" }";
JsonNode jsonNode = objectMapper.readTree(json);
String color = jsonNode.get("color").asText();
// Output: color -> Black
复制代码
String jsonCarArray =
"[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
List<Car> listCar = objectMapper.readValue(jsonCarArray, new TypeReference<List<Car>>(){});
复制代码
String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
Map<String, Object> map = objectMapper.readValue(json, new TypeReference<Map<String,Object>>(){});
复制代码
ObjectMapper
的经常使用配置忽略不识别的字段(json属性与目标实体存在属性上的差别):
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
复制代码
容许原始值为null:
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);
复制代码
容许将枚举序列化/反序列化为数字:
objectMapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, false);
复制代码
假设有一个序列化器:
public class CustomCarSerializer extends StdSerializer<Car> {
public CustomCarSerializer() {
this(null);
}
public CustomCarSerializer(Class<Car> t) {
super(t);
}
@Override
public void serialize( Car car, JsonGenerator jsonGenerator, SerializerProvider serializer) {
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("car_brand", car.getType());
jsonGenerator.writeEndObject();
}
}
复制代码
一个反序列化器:
public class CustomCarDeserializer extends StdDeserializer<Car> {
public CustomCarDeserializer() {
this(null);
}
public CustomCarDeserializer(Class<?> vc) {
super(vc);
}
@Override
public Car deserialize(JsonParser parser, DeserializationContext deserializer) {
Car car = new Car();
ObjectCodec codec = parser.getCodec();
JsonNode node = codec.readTree(parser);
// try catch block
JsonNode colorNode = node.get("color");
String color = colorNode.asText();
car.setColor(color);
return car;
}
}
复制代码
用ObjectMapper
使用他们:
//添加自定义序列化器
module.addSerializer(Car.class, new CustomCarSerializer());
//添加自定义反序列化器
module.addDeserializer(Car.class, new CustomCarDeserializer());
复制代码
ObjectMapper objectMapper = new ObjectMapper();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z");
objectMapper.setDateFormat(df);
复制代码
反序列化为数组:
String jsonCarArray =
"[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);
Car[] cars = objectMapper.readValue(jsonCarArray, Car[].class);
复制代码
反序列化为集合:
String jsonCarArray =
"[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
ObjectMapper objectMapper = new ObjectMapper();
List<Car> listCar = objectMapper.readValue(jsonCarArray, new TypeReference<List<Car>>(){});
复制代码