java:jackson 一:Jackson Annotation

java:jackson 一:Jackson Annotation

1 前言

参考文档地址:

https://www.baeldung.com/jackson

https://www.baeldung.com/jackson-annotations

2 使用

2.1 Jackson Serialization Annotations

jackson 序列化注解


2.1.1 @JsonAnyGetter

The @JsonAnyGetter annotation allows for the flexibility of using a Map field as standard properties.

package com.xiaoxu.test.jackson;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.text.StringEscapeUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * @author xiaoxu
 * @date 2022-12-21
 * spring_boot:com.xiaoxu.test.jackson.TestJaskSon
 */
public class TestJaskSon {

    public static void main(String[] args) throws Exception{
        ExtendableBean bean = new ExtendableBean("My bean");
        bean.add("attr1", "val1");
        bean.add("attr2", "val2");

        System.out.println(bean);

        String result = new ObjectMapper().writeValueAsString(bean);
        System.out.println(result);

        String a = "{\\\"name\\\":\\\"xiaoxu\\\",\\\"age\\\":\\\"27\\\"}";
        String s = StringEscapeUtils.unescapeJava(a);
        System.out.println(s);
        UseRR useRR = JSON.parseObject(s, UseRR.class);
        System.out.println(useRR);
    }
}

class UseRR{
    String name;

    String age;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(String age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "UseRR{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }
}

class ExtendableBean {
    public String name;
    private Map<String, String> properties;

    ExtendableBean(String name){
        this.name = name;
        this.properties = new HashMap<>();
    }

    public void add(String key,String value){
        this.properties.put(key,value);
    }

    @JsonAnyGetter
    public Map<String, String> getProperties() {
        return properties;
    }

    @Override
    public String toString() {
        return "ExtendableBean{" +
                "name='" + name + '\'' +
                ", properties=" + properties +
                '}';
    }
}
ExtendableBean{name='My bean', properties={attr2=val2, attr1=val1}}
{"name":"My bean","attr2":"val2","attr1":"val1"}
{"name":"xiaoxu","age":"27"}
UseRR{name='xiaoxu', age='27'}

可见,@JsonAnyGetter加在Map属性的get方法上时,打印的json字符串为将Map属性的key、value也直接展示在json结果中了。


2.1.2 @JsonGetter

The @JsonGetter annotation is an alternative to the @JsonProperty annotation, which marks a method as a getter method.

先观察@JsonProperty的使用:

如下DTO的name属性的set和get方法名称,不是传统的setter、getter方法名称:

package test.jackson;

import lombok.AllArgsConstructor;

/**
 * @author xiaoxu
 * @date 2022-12-27
 * java_demo:test.jackson.JacksonDTO
 */
@AllArgsConstructor
public class JacksonDTO {
    int id;
    String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getMyName() {
        return name;
    }

    public void setMyName(String name) {
        this.name = name;
    }
}
package test.jackson;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

/**
 * @author xiaoxu
 * @date 2022-12-27
 * java_demo:test.jackson.JacksonAnnotationTest
 */
public class JacksonAnnotationTest {
    private static final ObjectMapper objectMapper;

    static {
        objectMapper = new ObjectMapper();
        objectMapper.configure(SerializationFeature.INDENT_OUTPUT,true);
    }

    public static void demo1() throws Exception{
        JacksonDTO jacksonDTO = new JacksonDTO(1,"xiaoxu");
        System.out.println(objectMapper.writeValueAsString(jacksonDTO));
    }

    public static void main(String[] args) throws Exception{
        demo1();
    }

}

上述执行结果如下,可见序列化后,不为name,是myName:

{
  "id" : 1,
  "myName" : "xiaoxu"
}

使用@JsonProperty:

package test.jackson;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.ToString;


/**
 * @author xiaoxu
 * @date 2022-12-27
 * java_demo:test.jackson.JacksonDTO
 */
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class JacksonDTO {
    @JsonProperty(value = "mid")
    int id;
    String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @JsonProperty(value = "xName")
    public String getMyName() {
        return name;
    }

//    @JsonProperty(value = "xName")
    public void setMyName(String name) {
        this.name = name;
    }
}
package test.jackson;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

/**
 * @author xiaoxu
 * @date 2022-12-27
 * java_demo:test.jackson.JacksonAnnotationTest
 */
public class JacksonAnnotationTest {
    private static final ObjectMapper objectMapper;

    static {
        objectMapper = new ObjectMapper();
        objectMapper.configure(SerializationFeature.INDENT_OUTPUT,true);
    }

    public static void demo1() throws Exception{
        JacksonDTO jacksonDTO = new JacksonDTO(1,"xiaoxu");
        System.out.println(objectMapper.writeValueAsString(jacksonDTO));
        /* 反序列化的前提:需要有无参构造方法,否则报错:
        *
        * (no Creators, like default constructor, exist):
        * cannot deserialize from Object value (no delegate- or property-based Creator)
        *  */
        JacksonDTO jacksonDTO1 = objectMapper.readerFor(JacksonDTO.class)
                .readValue(objectMapper.writeValueAsString(jacksonDTO));
        System.out.println(jacksonDTO1);
    }

    public static void main(String[] args) throws Exception{
        demo1();
    }

}

序列化结果:

{
  "mid" : 1,
  "xName" : "xiaoxu"
}
JacksonDTO(id=1, name=xiaoxu)

@JsonGetter可替代如上@JsonProperty注解使用:

在这里插入图片描述

再次执行,序列化的效果一致:

在这里插入图片描述


2.1.3 @JsonPropertyOrder

We can use the @JsonPropertyOrder annotation to specify the order of properties on serialization.

@JsonPropertyOrder主要是更新序列化后的结果的字段顺序,如果同时存在使用了@JsonProperty注解,必须按照@JsonProperty注解的value设置值,才能更新顺序成功(无法匹配则没有效果)。

@ToString
@AllArgsConstructor
@NoArgsConstructor
@JsonPropertyOrder(value = {"xxName","mid"})
public class JacksonDTO {
    @JsonProperty(value = "mid")
    int id;
    String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @JsonGetter(value = "xxName")
    public String getMyName() {
        return name;
    }

//    @JsonProperty(value = "xName")
    public void setMyName(String name) {
        this.name = name;
    }
}

再次执行,DTO的字段顺序改变:

在这里插入图片描述


2.1.4 @JsonRawValue

The @JsonRawValue annotation can instruct Jackson to serialize a property exactly as is.

@ToString
@AllArgsConstructor
@NoArgsConstructor
/* 序列化时,有getter方法即可 */
@Getter
public class JacksonDTO1 {
    int id;
    String name;
    @JsonRawValue
    String jsonData;
}
JacksonDTO1 jacksonDTO1 = new JacksonDTO1(1,"xiaoxu","{\"myName\":\"xiaoxu\",\"age\":\"55\"}");
System.out.println(objectMapper.writeValueAsString(jacksonDTO1));

执行结果:

{
  "id" : 1,
  "name" : "xiaoxu",
  "jsonData" : {"myName":"xiaoxu","age":"55"}
}

2.1.5 @JsonValue

@JsonValue indicates a single method that the library will use to serialize the entire instance.

For example, in an enum, we annotate the getName with @JsonValue so that any such entity is serialized via its name.

enum JackEnum{
    Study("study",1234);

    private String code;
    private long value;

    JackEnum(String code, long value){
        this.code = code;
        this.value = value;
    }

    @JsonValue
    public String getCode() {
        return code;
    }

    public long getValue() {
        return value;
    }
}
System.out.println(objectMapper.writeValueAsString(JackEnum.Study));

执行结果:

"study"

2.1.6 @JsonRootName

The @JsonRootName annotation is used, if wrapping is enabled, to specify the name of the root wrapper to be used.

Wrapping means that instead of serializing a User to something like:

@ToString
@AllArgsConstructor
@NoArgsConstructor
/* 序列化时,有getter方法即可 */
@Getter
@JsonRootName(value = "specialPerson")
class JacksonDTO2 {
    int id;
    String name;
}
/* 不增加 objectMapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
* @JsonRootName(value = "specialPerson") 将不会生效
*  */
objectMapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
JacksonDTO2 jacksonDTO2 = new JacksonDTO2(1,"xiaoxu");
System.out.println(objectMapper.writeValueAsString(jacksonDTO2));

执行结果:

{
  "specialPerson" : {
    "id" : 1,
    "name" : "xiaoxu"
  }
}

2.1.7 @JsonSerialize

We’re going to use @JsonSerialize to serialize the eventDate property with a CustomDateSerializer:

该注解常用于和自定义序列化(或类似@JsonDeserialize,与自定义反序列化)器一同使用

使用参考如下:

https://blog.csdn.net/a232884c/article/details/128418713

2.2 Jackson Deserialization Annotations

jackson 反序列化注解


2.2.1 @JsonCreator

We can use the @JsonCreator annotation to tune the constructor/factory used in deserialization.

It’s very useful when we need to deserialize some JSON that doesn’t exactly match the target entity we need to get.

去掉@JsonCreator,只使用@JsonProperty,效果是一样的:

@ToString
class JacksonDTO3 {
    int id;
    String name;

    /* 构造方法为反序列化时的myName,映射为name */
    @JsonCreator
    public JacksonDTO3(@JsonProperty("id") int id,
                       @JsonProperty("myName") String name){
        this.id = id;
        this.name = name;
    }
}
String value = "{\"id\":\"123\",\"myName\":\"xiaoxu\"}";
JacksonDTO3 dto3 = objectMapper.readerFor(JacksonDTO3.class)
        .readValue(value);
System.out.println(dto3);

执行结果:

JacksonDTO3(id=123, name=xiaoxu)

2.2.2 @JacksonInject

@JacksonInject indicates that a property will get its value from the injection and not from the JSON data.

In the following example, we use @JacksonInject to inject the property id:

@ToString
class JacksonDTO4 {
    @JacksonInject
    int id;
    String name;

    /* id 是注入的, 但是name反序列化时,取的jsonData中的,
    * 必须加上getter方法,否则将会抛出异常
    *  */
    public String getName() {
        return name;
    }
}
String value = "{\"name\":\"xiaoxu\"}";
InjectableValues inject = new InjectableValues.Std().addValue(int.class, 666);
JacksonDTO4 dto4 = objectMapper.reader(inject)
        .forType(JacksonDTO4.class)
        .readValue(value);
System.out.println(dto4);

执行结果:

JacksonDTO4(id=666, name=xiaoxu)

2.2.3 @JsonAnySetter

@JsonAnySetter allows us the flexibility of using a Map as standard properties. On deserialization, the properties from JSON will simply be added to the map.

@ToString
class ExtendableBean {
    public String name;
    private final Map<String, String> properties = new HashMap<>();

    @JsonAnySetter
    public void add(String key, String value) {
        properties.put(key, value);
    }
}
String json
        = "{\"name\":\"xiaoxu\",\"attr2\":\"val2\",\"attr1\":\"val1\"}";

ExtendableBean bean = objectMapper
        .readerFor(ExtendableBean.class)
        .readValue(json);
System.out.println(bean);

执行结果:

ExtendableBean(name=xiaoxu, properties={attr2=val2, attr1=val1})

2.2.4 @JsonSetter

@JsonSetter is an alternative to @JsonProperty that marks the method as a setter method.

This is incredibly useful when we need to read some JSON data, but the target entity class doesn’t exactly match that data, and so we need to tune the process to make it fit.

此注解和@JsonGetter效果类似,只是用于的是反序列化

@ToString
class JacksonDTO5 {
    int id;
    String name;

    /* 反序列化时,id 有setter或者getter方法均可 */
    public void setId(int id) {
        this.id = id;
    }

    @JsonSetter("name")
    public void setMyName(String name) {
        this.name = name;
    }
}
String value = "{\"id\":\"123999\",\"name\":\"xiaoxu\"}";
JacksonDTO5 dto5 = objectMapper.readerFor(JacksonDTO5.class)
        .readValue(value);
System.out.println(dto5);

执行结果:

JacksonDTO5(id=123999, name=xiaoxu)

2.2.5 @JsonDeserialize

@JsonDeserialize indicates the use of a custom deserializer.

该注解@JsonDeserialize用于和自定义反序列化器一同使用

使用参考如下:

https://blog.csdn.net/a232884c/article/details/128407205

2.2.6 @JsonAlias

The @JsonAlias defines one or more alternative names for a property during deserialization.

@ToString
class JacksonDTO6 {
    int id;
    @JsonAlias(value = {"f_name","frName"})
    String fruitName;

    /* 反序列化时,id 有setter或者getter方法均可 */
    public void setId(int id) {
        this.id = id;
    }

    /* 反序列化时,fruitName 有setter或者getter方法均可 */
    public String getFruitName() {
        return fruitName;
    }
}
String value = "{\"id\":\"123888\",\"frName\":\"xiaoxu\"}";
JacksonDTO6 dto6 = objectMapper.readerFor(JacksonDTO6.class)
        .readValue(value);
System.out.println(dto6);

执行结果:

JacksonDTO6(id=123888, fruitName=xiaoxu)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值