使用Jackson定制化某字段的序列化/反序列化(Jackson – Decide What Fields Get Serialized/Deserialized)

目录

    • A Public Field
      • 有get,set方法时,则序列化,反序列化都支持
      • 无get,set方法时,则序列化,反序列化仅支持public
      • 反序列化仅支持public字段,如果JSON串包含其他字段否则无法识别,从而报错
    • A Getter Makes a Non-Public Field Serializable and Deserializable
      • 有get方法的Non-Public Field支持序列化和反序列化
      • Json串反序列化时,仅支持有get方法的Non-Public Field,否则无法解析报错
    • A Setter Makes a Non-Public Field Deserializable Only
      • the setter should only make the field deserializable, but not serializable:
      • 只能解析有set方法属性,否则报错
    • Make All Fields Globally Serializable
    • Change the Name of a Property on Serialization/Deserialization
    • Ignore a Field on Serialization or Deserialization

A Public Field

有get,set方法时,则序列化,反序列化都支持

@Data
@AllArgsConstructor
@NoArgsConstructor
public class MyDtoAccessLevel {
    private String stringValue;
    int intValue;
    protected float floatValue;
    public boolean booleanValue;
}
ObjectMapper mapper = new ObjectMapper();
MyDtoAccessLevel dtoObject = new MyDtoAccessLevel();
String dtoAsString = mapper.writeValueAsString(dtoObject);
System.out.println(dtoAsString);

String jsonAsString = "{\"stringValue\":\"dtoString\"}";
MyDtoAccessLevel dtoObject1 = mapper.readValue(jsonAsString, MyDtoAccessLevel.class);
System.out.println(dtoObject1);

执行结果
{"stringValue":null,"intValue":0,"floatValue":0.0,"booleanValue":false}
MyDtoAccessLevel(stringValue=dtoString, intValue=0, floatValue=0.0, booleanValue=false)

无get,set方法时,则序列化,反序列化仅支持public

public class MyDtoAccessLevel {
    private String stringValue;
    int intValue;
    protected float floatValue;
    public boolean booleanValue;

    @Override
    public String toString() {
        return "MyDtoAccessLevel{" + "stringValue='" + stringValue + '\'' + ", intValue=" + intValue + ", floatValue=" + floatValue + ", booleanValue=" + booleanValue + '}';
    }
}
ObjectMapper mapper = new ObjectMapper();
MyDtoAccessLevel dtoObject = new MyDtoAccessLevel();
String dtoAsString = mapper.writeValueAsString(dtoObject);
System.out.println(dtoAsString);

String jsonAsString = "{\"booleanValue\":false}";
MyDtoAccessLevel dtoObject1 = mapper.readValue(jsonAsString, MyDtoAccessLevel.class);
System.out.println(dtoObject1);

结果
{"booleanValue":false}
MyDtoAccessLevel{stringValue='null', intValue=0, floatValue=0.0, booleanValue=false}

反序列化仅支持public字段,如果JSON串包含其他字段否则无法识别,从而报错

String jsonAsString = "{\"booleanValue\":false,\"stringValue\":\"dtoString\"}";
MyDtoAccessLevel dtoObject1 = mapper.readValue(jsonAsString, MyDtoAccessLevel.class);
System.out.println(dtoObject1);

Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "stringValue" (class javabasic.enumprac.MyDtoAccessLevel), not marked as ignorable (one known property: "booleanValue"])
 at [Source: (String)"{"booleanValue":false,"stringValue":"dtoString"}"; line: 1, column: 38] (through reference chain: javabasic.enumprac.MyDtoAccessLevel["stringValue"])

A Getter Makes a Non-Public Field Serializable and Deserializable

public class MyDtoWithGetter {
    private String stringValue;
    private int intValue;

    public String getStringValue() {
        return stringValue;
    }

    @Override
    public String toString() {
        return "MyDtoWithGetter{" + "stringValue='" + stringValue + '\'' + ", intValue=" + intValue + '}';
    }
}

有get方法的Non-Public Field支持序列化和反序列化

ObjectMapper mapper = new ObjectMapper();
MyDtoWithGetter dtoObject = new MyDtoWithGetter();
String dtoAsString = mapper.writeValueAsString(dtoObject);
System.out.println(dtoAsString);

String jsonAsString = "{\"stringValue\":\"dtoString\"}";
MyDtoWithGetter dtoObject1 = mapper.readValue(jsonAsString, MyDtoWithGetter.class);
System.out.println(dtoObject1);

结果
{"stringValue":null}
MyDtoWithGetter{stringValue='dtoString', intValue=0}

Json串反序列化时,仅支持有get方法的Non-Public Field,否则无法解析报错

String jsonAsString = "{\"intValue\":11,\"stringValue\":\"dtoString\"}";
MyDtoWithGetter dtoObject1 = mapper.readValue(jsonAsString, MyDtoWithGetter.class);

Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "intValue" (class javabasic.enumprac.MyDtoWithGetter), not marked as ignorable (one known property: "stringValue"])
 at [Source: (String)"{"intValue":11,"stringValue":"dtoString"}"; line: 1, column: 15] (through reference chain: javabasic.enumprac.MyDtoWithGetter["intValue"])

A Setter Makes a Non-Public Field Deserializable Only

public class MyDtoWithSetter {
    private String stringValue;
    private int intValue;

    public void setIntValue(int intValue) {
        this.intValue = intValue;
    }

    @Override
    public String toString() {
        return "MyDtoWithSetter{" + "stringValue='" + stringValue + '\'' + ", intValue=" + intValue + '}';
    }
}

the setter should only make the field deserializable, but not serializable:

ObjectMapper mapper = new ObjectMapper();
MyDtoWithSetter  dtoObject = new MyDtoWithSetter ();
String dtoAsString = mapper.writeValueAsString(dtoObject);
System.out.println(dtoAsString);

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class javabasic.enumprac.MyDtoWithSetter and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)

只能解析有set方法属性,否则报错

ObjectMapper mapper = new ObjectMapper();
String jsonAsString = "{\"intValue\":1}";
MyDtoWithSetter dtoObject1 = mapper.readValue(jsonAsString, MyDtoWithSetter.class);
System.out.println(dtoObject1);

MyDtoWithSetter{stringValue='null', intValue=1}
ObjectMapper mapper = new ObjectMapper();
String jsonAsString = "{\"stringValue\":\"dtoString\",\"intValue\":\"22\"}";
MyDtoWithSetter dtoObject1 = mapper.readValue(jsonAsString, MyDtoWithSetter.class);
System.out.println(dtoObject1);

Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "stringValue" (class javabasic.enumprac.MyDtoWithSetter), not marked as ignorable (one known property: "intValue"])
 at [Source: (String)"{"stringValue":"dtoString","intValue":"22"}"; line: 1, column: 17] (through reference chain: javabasic.enumprac.MyDtoWithSetter["stringValue"])

Make All Fields Globally Serializable

public class MyDtoAccessLevel {
    private String stringValue;
    int intValue;
    protected float floatValue;
    public boolean booleanValue;

    @Override
    public String toString() {
        return "MyDtoAccessLevel{" + "stringValue='" + stringValue + '\'' + ", intValue=" + intValue + ", floatValue=" + floatValue + ", booleanValue=" + booleanValue + '}';
    }
}
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

MyDtoAccessLevel dtoObject = new MyDtoAccessLevel();

String dtoAsString = mapper.writeValueAsString(dtoObject);
System.out.println(dtoAsString);

{"stringValue":null,"intValue":0,"floatValue":0.0,"booleanValue":false}

Change the Name of a Property on Serialization/Deserialization

针对相同的输出代码

 ObjectMapper mapper = new ObjectMapper();
 MyDto dtoObject = new MyDto();
 dtoObject.setStringValue("a");
 
 String dtoAsString = mapper.writeValueAsString(dtoObject);
 System.out.println(dtoAsString);
public class MyDto {
    private String stringValue;

    public MyDto() {
        super();
    }

    public String getStringValue() {
        return stringValue;
    }

    public void setStringValue(String stringValue) {
        this.stringValue = stringValue;
    }
}

结果
{"stringValue":"a"}
public class MyDto {
    private String stringValue;

    public MyDto() {
        super();
    }

    @JsonProperty("strVal")
    public String getStringValue() {
        return stringValue;
    }

    public void setStringValue(String stringValue) {
        this.stringValue = stringValue;
    }
}

结果
{"strVal":"a"}

Ignore a Field on Serialization or Deserialization

Further reading: Jackson Ignore Properties on Marshalling

通过在getter上添加@JsonIgnore注释禁止该字段的序列化,通过在setter上应用@JsonProperty注释来启用该字段的反序列化

public class User {
    public String name;
    private String password;

    @JsonIgnore
    public String getPassword() {
        return password;
    }

    @JsonProperty
    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" + "name='" + name + '\'' + ", password='" + password + '\'' + '}';
    }
}
ObjectMapper mapper = new ObjectMapper();

User userObject = new User();
userObject.setPassword("thePassword");
userObject.setPassword("mingming");

String userAsString = mapper.writeValueAsString(userObject);
System.out.println(userAsString);

String jsonAsString = "{\"name\":\"mingming\",\"password\":\"thePassword\"}";
User userObject1 = mapper.readValue(jsonAsString, User.class);
System.out.println(userObject1);

结果:
{"name":null}
User{name='mingming', password='thePassword'}

-----------------------------------------------------------------------------读书笔记摘自 文章:Jackson – Decide What Fields Get Serialized/Deserialized

你可能感兴趣的:(Baeldung,学习笔记,基础知识,java,开发语言)