前两天我在处理业务的时候遇到一个问题,需要在定义好的实体类中动态添加一些客户自定义的字段,序列化为 JSON 字符串返回给前端使用。
比如定义了一个学生的实体类 Student,类中只有 id、name 两个字段:
public class Student {
private String id;
private String name;
// get set function
}
在学生的设置页面,用户可以根据需要添加一些自定义属性,比如 age、address 等,因为属性名不确定,所以我们也没办法提前在 Student 类中定义这些属性。
在没有使用 Jackson 提供的特性之前,我们能想到的是在 Student 类中增加一个 Map 类型的字段来存放用户自定义的属性,写法如下所示。
public class Student {
private String id;
private String name;
private Map<String, String> customFields = new HashMap<>();
// get set function
}
这样序列化后,返回给前端的 JSON 字符串的内容如下所示。
{
"id": "1",
"name": "张三",
"customFields": {
"address": "suzhou",
"age": "12"
}
}
用户自定义的属性没有合并到 Student 对象的属性中,还是独立放在 customFields 字段中。我们希望给到前端的 JSON 数据内容如下所示。
{
"id": "1",
"name": "张三",
"address": "suzhou",
"age": "12"
}
这就需要利用 Jackson 的一些特性了,它提供了两个注解可以完美的解决这个问题,@JsonAnyGetter & @JsonAnySetter,使用方法如下所示。
public class Student {
private String id;
private String name;
private Map<String, String> customFields = new HashMap<>();
@JsonAnyGetter
public Map<String, String> getCustomFields() {
return customFields;
}
@JsonAnySetter
public void setCustomFields(String key, String value) {
this.customFields.put(key, value);
}
// get set function
}
在 getCustomFields 方法上添加 @JsonAnyGetter 注解,在 setCustomFields 方法上添加 @JsonAnySetter,这样不管是序列化为 JSON 字符串还是反序列化为 Java 对象都可以实现了。
需要注意 setCustomFields 方法的参数,不能是 customFields 字段,因为前端传过来的 JSON 字符串中没有这个字段,所以只能提供两个参数 key 和 value,反序列化时,Jackson 会自动把自定义的属性添加到 customFields 字段中。
测试方法如下所示。
public static void main(String[] args) throws JsonProcessingException {
Student student = new Student();
student.setId("1");
student.setName("张三");
student.setCustomFields("age", "12");
student.setCustomFields("address", "suzhou");
String jsonStr = OBJECT_MAPPER.writeValueAsString(student);
System.out.println(jsonStr);
Student student1 = OBJECT_MAPPER.readValue(jsonStr, Student.class);
Map<String, String> customFields = student1.getCustomFields();
for(Map.Entry<String, String> entry : customFields.entrySet()) {
System.out.println("key: "+ entry.getKey() + ", value: " + entry.getValue());
}
}
参考:Jackson @JsonAnyGetter and @JsonAnySetter Example
作者:殷建卫 链接:https://www.yuque.com/yinjianwei/vyrvkf/ptyd7w 来源:殷建卫 - 架构笔记 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。