Jackson详解

简述

  Jackson是springboot默认使用的一个Json序列化和反序列化的库,非常流行且高效,API设计灵活容易扩展和定制化。

ObjectMapper

  ObjectMapper作为Jackson的门户,他是基于对象绑定的API。可以通过ObjectMapper把json串反序列化为java类,也可以将java类序列化为json串。

  下面的例子我们以User类作为实例

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Integer id;
    private String username;
    private Integer age;
}

把json串反序列化为对象

  我们可以使用ObjectMapper的readValue()方法,参数是json串和我们想要反序列化成的类

objectMapper.readValue(str, Student.class);// str是json字符串

  如果想反序列化成特殊类型,可以使用下面的方法

objectMapper.readValue(str, Student[].class);// 数组
objectMapper.readValue(str, new TypeReference<List<Student>>() {});// list
objectMapper.readValue(str, new TypeReference<Map<String,String>>() {});// map

把对象序列化为json串

  我们可以使用ObjectMapper的writeValueAsString()方法,参数我们想序列化的类

objectMapper.writeValueAsString(student);

Jackson常用注解

@JsonIgnoreProperties

  当json属性比java类中的属性多的时候,我们可以使用@JsonIgnoreProperties注解标注在类上,value里填写哪些属性需要忽略

  或者标注@JsonIgnoreProperties(ignoreUnknown = true)表示忽略所有不认识的属性

@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties({"address"})
public class User {
    private Integer id;
    private String username;
    private Integer age;
}

@JsonIgnore

  当json属性比java类中的属性少的时候,我们可以使用@JsonIgnore注解标注在属性上,表示忽略该属性

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Integer id;
    private String username;
    @JsonIgnore
    private Integer age;
}

  或使用@JsonIgnoreType标注在类上,表示忽略整个类的多余属性

@JsonProperty

  @JsonProperty注解用于解决json属性名和java属性名不一致的情况,在属性上进行标注,value表示json的属性名

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Integer id;
    private String username;
    @JsonProperty("userAge")
    private Integer age;
}

@JsonUnwrapped

  @JsonUnwrapped注解表示该属性以扁平的数据结构序列化或反序列化

  例如我们的User类中的name属性是一个类,包含firstName和lastName

public class Name {
    private String firstName;
    private String lastName;
}

  如果我们想在User类序列号的时候将这个name摊平\扁平地显示,我们需要在name上标注@JsonUnwrapped

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Integer id;
    @JsonUnwrapped
    private Name username;
    private Integer age;
}

@JsonValue

  @JsonValue注解一个类只能有一个,标注在属性上,表示json序列化的时候只序列化这一个值

  像这样Student类序列化的时候就只会序列化name这一个属性

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    @JsonValue
    private String name;
    private Integer age;
}

  也可以标注在方法上,表示该方法的返回值会成为这个类的序列化结果

  像这样Student的序列化结果就会只有一个result,如果返回值是类的话会Student类的序列化结果就是返回值这个类的序列化结果

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    private String name;
    private Integer age;
    
    @JsonValue
    public String getJsonValue(){
        return "result";
    }
}

@JsonFormat

  @JsonFormat注解标注在属性上,用于指定时间的序列化和反序列化结果格式

  例如这样指定类Date类的pattern和时区

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    private String name;
    private Integer age;
    @JsonFormat(pattern="yyyy-MM-dd",timezone="GMT+8")
    private Date time;
}

 

@JsonInclude

  @JsonInclude注解标注在属性上,他会告诉jackson这个属性满足什么条件的时候才会被序列化

  像这样表示username属性不为空的时候才会参与序列化

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Integer id;
    @JsonInclude(Include.NON_NULL)
    private Name username;
    private Integer age;
}

  常用的还有NON_EMPTY和NON_DEFAULT

 

自定义序列化器和反序列化器

  以上是Jackson提供的帮助我们定制序列化 / 反序列化的注解

  如果我们需要更加客制化地进行序列化和反序列化,我们可以自定义我们的序列化器和反序列化器

  如果现在我们需要序列化Student类,其中的time属性我们希望通过毫秒值进行序列化

  我们要在time属性上标注@JsonSerialize,并指定我们自定义的序列化器

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    private String name;
    private Integer age;
    @JsonSerialize(using = DateSerializer.class)
    private Date time;
}

  然后我们创建DateSerializer类,这是我们自定义的序列化器,然后继承标准的序列化器,重写serialize方法

  其中value就是当前需要序列化的类,我们使用gen的writeNumber方法输出我们的序列化结果

public class DateSerializer extends StdSerializer<Date> {

    protected DateSerializer() {
        super(Date.class);
    }

    @Override
    public void serialize(Date value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        long epochMilli = value.getTime();
        gen.writeNumber(epochMilli);
    }
}

  反序列化也是同理的,return的结果就是反序列化的结果

public class DateDeserializer extends StdDeserializer<Date> {

    protected DateDeserializer() {
        super(Date.class);
    }

    @Override
    public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        long epochMilli = p.getLongValue();
        return new Date(epochMilli);
    }
}

 

 

 

 

  

 

posted @ 2022-10-25 17:56  艾尔夏尔-Layton  阅读(292)  评论(0编辑  收藏  举报