前两天我在处理业务的时候遇到一个问题,需要在定义好的实体类中动态添加一些客户自定义的字段,序列化为 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<>();@JsonAnyGetterpublic Map<String, String> getCustomFields() {return customFields;}@JsonAnySetterpublic 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 来源:殷建卫 - 架构笔记 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
