Jackson的注解

参考:https://blog.csdn.net/sdyy321/article/details/40298081

jackson 1.x 和 2.x版本的注解,分别放在不同的包下:

  • 1.x是在jackson core jarorg.codehaus.jackson.annotate
  • 2.x是在jackson-databindcom.fasterxml.jackson.annotation

@JsonAutoDetect

作用
作用在类上,用来开启/禁止自动检测。

jackson的自动检测机制
jackson会自动检测目标实体类的字段,即使没有使用JsonProperty注解,也会进行序列化/反序列化,检测顺序如下:所有被public修饰的字段->所有被public修饰的getter->所有被public修饰的setter

设置自动检测可见级别 JsonAutoDetect.Visibility

  1. ANY:任何级别的字段都可以自动识别
  2. NONE:所有字段都不可以自动识别
  3. NON_PRIVATE:非private修饰的字段可以自动识别
  4. PROTECTED_AND_PUBLIC: 被protected和public修饰的字段可以被自动识别
  5. PUBLIC_ONLY: 只有被public修饰的字段才可以被自动识别
  6. DEFAULT: PUBLIC_ONLY

示例

// 字段自动检测可见级别
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY)
// getter自动检测可见级别
@JsonAutoDetect(getterVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY)
// boolean类型的getter方法:isXxx
@JsonAutoDetect(isGetterVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY)
// setter自动检测可见级别
@JsonAutoDetect(setterVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY)
// 构造自动检测可见级别
@JsonAutoDetect(creatorVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY)

SerializationFeature

配置SerializationFeature

objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE,true);
  1. SerializationFeature.WRAP_ROOT_VALUE:是否环绕根元素,可以使用@JsonRootName定义根元素的名称
  2. SerializationFeature.INDENT_OUTPUT:是否缩放排列输出,默认false,有些场合为了便于排版阅读则需要对输出做缩放排列(即格式化后的json字符串)
  3. SerializationFeature.WRITE_ENUMS_USING_TO_STRING:序列化枚举是以toString()来输出,默认false,即默认以name()来输出
  4. SerializationFeature.WRITE_ENUMS_USING_INDEX:列化枚举是以ordinal()来输出,默认false
  5. SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED:序列化单元素数组时不以数组来输出,默认false
  6. SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS:序列化Map时对key进行排序操作,默认false
  7. SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS:序列化char[]时以json数组输出,默认false
  8. SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN:序列化BigDecimal时之间输出原始数字还是科学计数,默认false,即是否以toPlainString()科学计数方式来输出

@JsonIgnore

作用在字段或方法上,用来完全忽略被注解的字段和方法对应的属性,即便这个字段或方法可以被自动检测到或者还有其他的注解。

示例:

@JsonIgnore
private String name;

@JsonIgnoreProperties

作用在类上,用来说明有些属性在序列化/反序列化时需要忽略掉,可以将它看做是@JsonIgnore的批量操作,但它的功能比@JsonIgnore要强,比如一个类是代理类,我们无法将将@JsonIgnore标记在属性或方法上,此时便可用@JsonIgnoreProperties标注在类声明上,它还有一个重要的功能是作用在反序列化时解析字段时过滤一些未知的属性,否则通常情况下解析到我们定义的类不认识的属性便会抛出异常。

忽略示例:

@JsonIgnoreProperties({"name","age","title"})
public static class TestPOJO{
  private int id;
  private String name;
  private int age;
  // setter/getter
}

过滤示例:

// json -> {name: "lisi", id = 1, age = 18, count = 100}
@JsonIgnoreProperties(ignoreUnknown=true)
public static class TestPOJO{
  private int id;
  private String name;
  private int age;
  // setter/getter
}
// 此时反序列化时,存在未知属性count,便不会抛出异常了

@JsonView

作用域方法和属性上,是一个Json视图模板,用来指定哪些属性可以包含在Json视图中。

优点

  1. 当实体类属性过多,但是展示json过少时,使用JsonIgnoreJsonIgnoreProperties就会显得过于繁琐,所以需要该注解。
  2. 多个控制器返回json时,每个json的字段都不同,但是java bean包含了这两个接口的所有字段,所以我们可以使用JsonView给字段‘分组’,使用参数 value指定视图分组

示例:

public class TestPOJO{
   @JsonView(FilterView.OutputA.class)
   private String a;
   @JsonView(FilterView.OutputA.class)
   private String c;
   @JsonView(FilterView.OutputB.class)
   private String d;
   @JsonView({FilterView.OutputB.class})
   private String b;
   //getters、setters忽略
}

// 定义视图标记
private static class FilterView {
    static class OutputA {}
    static class OutputB {}
}

序列化:

ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper
    .writerWithView(FilterView.OutputA.class) // 指定视图
    .writeValueAsString(testPOJO); // 序列化为字符串

@JsonFilter

作用于类,同JsonView类似,用于过滤不想要的属性,JsonFilter可以动态过滤属性,比如过滤调已sys开头的所有属性。

// 配置过滤器
ObjectMapper objectMapper = new ObjectMapper();
FilterProvider filters = new SimpleFilterProvider()
    .addFilter("myFilter",SimpleBeanPropertyFilter.filterOutAllExcept("a")); // 多虑调a属性以外的多有属性
objectMapper.setFilters(filters);
// 使用过滤器
@JsonFilter("myFilter")
public static class TestPOJO{
    private String a;
    private String c;
    private String d;
    private String b;
    //getters、setters省略
}

根据MixIn过滤属性

有时我们需要对已有的POJO进行属性过滤,但是不允许修改原有的POJO的代码,无法给他加上@JsonFilter注解,我们可以使用MixIn解决这个问题。

// POJO不可修改
public static class TestPOJO{
    private String a;
    private String c;
    private String d;
    private String b;
    //getters、setters省略
}
@JsonFilter("myFilter")
private static interface MyFilterMixIn{
}
ObjectMapper objectMapper = new ObjectMapper();
FilterProvider filters = new SimpleFilterProvider()
    .addFilter("myFilter",SimpleBeanPropertyFilter.filterOutAllExcept("a"));
objectMapper.setFilters(filters);
objectMapper.addMixInAnnotations(TestPOJO.class,MyFilterMixIn.class);
String jsonStr = objectMapper.writeValueAsString(testPOJO);

自定义JsonFilter todo

@JsonIgnoreType

作用于类,表示被注解该类型的属性将不会被序列化和反序列化,也跟上面几个一样属于过滤属性功能的注解

public static class TestPOJO{
    private Sub sub1;
    private Sub sub2;
    private MyIn myIn;
    private String name;
    //getters、setters省略
}

public static class MyIn{
    private int id;
    //getters、setters省略
}

@JsonIgnoreType
public static class Sub extends MyIn{
    private String name;
    //getters、setters省略
}

// TestPOJO被序列化时,Sub类型的两个属性sub1,sub2都将不会被序列化

@JsonProperty

作用在字段或方法上,用来对属性的序列化/反序列化,可以用来避免遗漏属性,同时提供对属性名称重命名,默认使用属性名称。

@JsonProperty("username") // 如果name没有setter/getter,则该注解必需,用来防止遗漏
private String name;

@JsonNaming 2.x

作用于类或方法, 和JsonProperty类似,是对JsonProperty的拓展。

有时业务需求要求,所有的json property name 都已xx_yy_zz的形式,而不是驼峰命名法。虽然使用 JsonProperty可以解决,但是每个属性都需要设置,过于繁琐,所以就提供了JsonNaming注解。

示例:

@JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class)
public static class TestPOJO{
    private String inReplyToUserId;
    // setter getter
}
// 得到的结果为:{in_reply_to_user_id:"xxx"}

Jackson已经提供了PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy,它可以将大写转换为小写并添加下划线,我们可以通过继承PropertyNamingStrategy.PropertyNamingStrategyBase来实现自己的策略,只需要重写String translate(String input)方法,生成并返回新的名称即可。

@JsonCreator

用于方法,通常用来标注构造方法或静态工厂方法上,使用该方法来构建实例,默认的是使用无参的构造方法,通常是和@JsonProperty@JacksonInject配合使用

标注在构造器上:

public static class TestPOJO{
    private String name;
    private int age;

    @JsonCreator
    public TestPOJO(@JsonProperty("full_name") String name,@JsonProperty("age") int age){
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
}

标注在静态方法上:

public static class TestPOJO{
    private String name;
    private Date birthday;

    private TestPOJO(String name,Date birthday){
        this.name = name;
        this.birthday = birthday;
    }

    @JsonCreator
    public static TestPOJO getInstance(@JsonProperty("name") String name,@JsonProperty("birthday") long timestamp){
        Date date = new Date(timestamp);
        return new TestPOJO(name,date);
    }
    public String getName() {
        return name;
    }
    public Date getBirthday() {
        return birthday;
    }
}

@JsonAnySetter

作用于方法,我们可以通过@JsonIgnoreProperties(ignoreUnknown=true)过滤未知属性,我们也可以使用@JsonAnySetter配合Map集合获取位置属性并存储。

public static class TestPOJO{
    private String name;
    private Map other = new HashMap();

    @JsonAnySetter
    public void set(String name,Object value) {
        other.put(name,value);
    }
    //getters、setters省略
}

@JsonAnyGetter

作用于方法,可以通过配置JsonAnyGetter的Map,来配置序列化时的额外属性。

public static class TestPOJO{
    private String name;
    private Map other = new HashMap();

    @JsonAnyGetter
    public Object get(String name) {
        return map.get(name);
    }
    //getters、setters省略
}
// 序列化时,map中的属性和值会注入到json字符串中

@JacksonInject

作用于属性、方法、构造参数上,被用来反序列化时标记已经被注入的属性

public static class TestPOJO{
    // 声明name已经被注入
    @JacksonInject("name")
    private String name;
    private int age;
    //getters、setters省略
}

注入name:

ObjectMapper objectMapper = new ObjectMapper();
String jsonStr = "{\"age\":12}";
InjectableValues inject = new InjectableValues.Std().addValue("name","myName");
TestPOJO testPOJO = objectMapper.reader(TestPOJO.class).with(inject).readValue(jsonStr);

@JsonFormat

作用在表示日期的属性或者字段上,用来将日期对象格式化为日期字符串,或者将格式化的日期字符串转换为日期对象。

示例:

@JsonFormat(pattern = "yyyy-MM-dd", locale = "zh", timezone = "GMT+8") // 日期格式化
private Date birthday;

多态类型处理

Jackson允许配置多态类型处理,在进行反序列化时,JSON数据类型可能出现多个子类型匹配,为了可以正确读取对象的类型,我们需要添加类型信息,可以通过以下几个注解实现。

@JsonTypeInfo

作用于类/接口,被用来开启多态类型处理,对基类/接口和子类/实现类都有效

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,include = JsonTypeInfo.As.PROPERTY,property = "name")

use属性定义使用哪一种类型识别码:

  1. JsonTypeInfo.Id.CLASS:使用完全限定类名做识别
  2. JsonTypeInfo.Id.MINIMAL_CLASS:若基类和子类在同一包类,使用类名(忽略包名)作为识别码
  3. JsonTypeInfo.Id.NAME:一个合乎逻辑的指定名称
  4. JsonTypeInfo.Id.CUSTOM:自定义识别码,由@JsonTypeIdResolver对应,稍后解释
  5. JsonTypeInfo.Id.NONE:不使用识别码

include(可选):指定识别码是如何被包含进去的:

  1. JsonTypeInfo.As.PROPERTY:作为数据的兄弟属性
  2. JsonTypeInfo.As.EXISTING_PROPERTY:作为POJO中已经存在的属性
  3. JsonTypeInfo.As.EXTERNAL_PROPERTY:作为扩展属性
  4. JsonTypeInfo.As.WRAPPER_OBJECT:作为一个包装的对象
  5. JsonTypeInfo.As.WRAPPER_ARRAY:作为一个包装的数组

property(可选):制定识别码的属性名称:

@JsonSerialize和@JsonDeserialize

作用于方法和字段上,通过 using(JsonSerializer)和using(JsonDeserializer)来指定序列化和反序列化的实现,通常我们在需要自定义序列化和反序列化时会用到,比如日期转换

日期转换

public static class TestPOJO{
    private String name;
    @JsonSerialize(using = MyDateSerializer.class)
    @JsonDeserialize(using = MyDateDeserializer.class)
    private Date birthday;
    //getters、setters省略
}
private static class MyDateSerializer extends JsonSerializer<Date>{
    @Override
    public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateStr = dateFormat.format(value);
        jgen.writeString(dateStr);
    }
}

private static class MyDateDeserializer extends JsonDeserializer<Date>{
    @Override
    public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        String value = jp.getValueAsString();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
        try {
            return dateFormat.parse(value);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
}

多态处理

@JsonPropertyOrder

作用在类上,被用来指明当序列化时需要对属性做排序

属性,alphabetic,boolean 是否采用字母拼音顺序排序,默认为false,不排序
属性,value,是一个string数组,表示将优先其他属性排序的属性名称

示例:

@JsonPropertyOrder(alphabetic = true,value = {"id","name"})
public class TestPOJO{}

也可以使用java代码:

objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY,true);

@JsonUnwrapped 2.x

作用在属性字段或方法上,用来将子JSON对象的所有属性添加到父元素中,替换父元素的属性

示例:

public static class TestPOJO{
    private int id;
    @JsonUnwrapped
    private TestName name;
    private int age;
    //getters、setters省略
}                                                                                               public static class TestName{
    private String firstName;
    private String secondName;
    //getters、setters省略
}

不使用注解的结果:

{"name":{"firstName":"张","lastName":"三"},"age":0}

使用注解的结果:

{"firstName":"张","lastName":"三","age":0}

@JsonIdentityInfo 2.x

作用于类或属性上,被用来在序列化/反序列化时为该对象或字段添加一个对象识别码,通常是用来解决循环嵌套的问题,比如数据库中的多对多关系

@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class,property = "@id")  
public static class Parent{
    private String name;
    private Child[] children;
    //getters、setters
}

public static class Child{
    private String name;
    private Parent parent;
    //getters、setters
}

1.6 提供了@JsonManagedReference和@JsonBackReference解决循环嵌套问题,已过时

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值