前后端分离开发中常用到的数据交互方式就是json。本文主要讲解对jackson对json的相关操作。
jackson
基础篇
1、引入依赖:
<!--jackson-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
2、、创建ObjectMapper常用配置
private static final ObjectMapper objectMapper;
static {
objectMapper = new ObjectMapper(); // 对象的所有字段全部列入,还是其他的选项,可以忽略null等
objectMapper.setSerializationInclusion(Include.ALWAYS); // 设置Date类型的序列化及反序列化格式
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); // 忽略空Bean转json的错误
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); // 忽略未知属性,防止json字符串中存在,而java对象中不存在对应属性的情况出现错误
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 注册一个时间序列化及反序列化的处理模块,用于解决jdk8中localDateTime等的序列化问题
objectMapper.registerModule(new JavaTimeModule());}
本文中用到的测试类,后续测试均使用本类
public class JsonUser {
private String userName;
private String pwd; private String address;
private List<String> user_phone;
private JsonPet pet; //基础篇还用不到,解决对象内嵌套问题
//省略构造器、get()、set()、toString()
}
public class JsonPet {
private String name;
private String age;
//省略构造器、get()、set()、toString()列
}
3、对象转json字符串
JsonUser user = new JsonUser("张三", "1246", "北京市海淀区", Collections.singletonList("15838609251")); //对象转json字符串 String s = objectMapper.writeValueAsString(user); System.out.println(s);
输出:
{“userName”:“张三”,“pwd”:“1246”,“address”:“北京市海淀区”,“user_phone”:“15838609251”}
注1:对象转json需要属性拥有get方法。这种方式是通过get方法来获取对象属性的,少几个get方法,输出的字符串就少几个属性。
注2:注:对象中的Map、List属性,转换的时候,会默认转换(不需要额外的配置)。
4、json字符串转对象
String str = "{\"userName\":\"张三\",\"pwd\":\"1246\",\"address\":\"北京市海淀区\",\"user_phone\":[\"15838609251\"]}"; JsonUser jsonUser = objectMapper.readValue(str, JsonUser.class);
基础篇到这里就结束了。想来,我们的小伙伴肯定有很多疑问,使用中肯定会遇到各种问题,下面的高级篇将进行详细讲解。
高级篇
问题1: 假设反序列化的json里面有个字段,在POJO类中没有,会反序列失败。
基础篇中的测试实体类JsonUser里面有一个字段pet,这也是一个实体类。
如果直接执行如下代码:
String str = "{\"userName\":\"张三\",\"pwd\":\"1246\",\"address\":\"北京市海淀区\",\"user_phone\":[\"15838609251\"],\"pet\":{\"name\":\"Jack\",\"age\":\"12\"}}";
JsonUser jsonUser = objectMapper.readValue(str,JsonUser.class);
会报错。
解决办法①:
修改JsonPet的有参构造方法
public class JsonPet {
private int age;
private String name;
@JsonCreator public
Person(@JsonProperty("age") int age, @JsonProperty("name") String name) {
this.age = age; this.name = name;
}
}
解决办法②:
自创建一个反序列化的方法
public class JsonPet {
private String name;
private String age;
public JsonPet() { }
public JsonPet(String name, String age) { this.name = name; this.age = age; }
/** * 反序列化时需要用的,支持Documentation:""的场景。 * 注:使用这种方式一定要有无参构造 */
@JsonCreator public static JsonPet create(String str) throws IOException {
//这个地方是对""进行处理
if (StringUtils.isBlank(str)) { return null; }
// 这里其实就是将value单独抽出来,再次进行反序列化;
return (new ObjectMapper()).readValue(str, JsonPet.class);
}
}
说明:
- 在反序列化时,Jackson默认会调用对象的无参构造函数,如果我们不定义任何构造函数,JVM会负责生成默认的无参构造函数。但是如果我们定义了构造函数,并且没有提供无参构造函数时,Jackson会报错;
- @JsonCreator 该注解用在对象的反序列时指定特定的构造函数或者工厂方法。如果默认构造函数无法满足需求,或者说我们需要在构造对象时做一些特殊逻辑,可以使用该注解。
- 如果是构造函数,则需要配合@JsonProperty来使用。
问题2: 假设反序列化的json里面有个字段,在POJO类中是泛型,如何处理。
解决办法:
借助于TypeReference类来处理。
JsonUser jsonUser = objectMapper.readValue(str, new TypeReference<Woman<Dog>>() {});
关于TypeReference
的用法可自行百度。
问题3: 假设反序列化的json里面有个字段名,和在POJO类中的字段名,不一致。
解决:在这个字段名前加注解 @JsonProperty。
注解很多,这里就不列举了,可自行百度。
!!!这里说一个小技巧!!!
找到jackson的注解包: com.fasterxml.jackson.annotation
在这个注解包下面,就是jackson的注解啦,感兴趣的小伙伴可以看一下。可以百度都搜一下感兴趣的。
最后的最后,送上干货,jackson在开发中使用的工具类
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)