JackSon
前后端分离开发中常用到的数据交互方式就是json。本文主要讲解对jackson对json的相关操作。
jackson
基础篇
1、引入依赖:
<dependency> <groupId>com.fasterxml.jackson.coregroupId> <artifactId>jackson-databindartifactId>
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在开发中使用的工具类😆😆😆
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;import java.io.IOException;
import java.text.SimpleDateFormat;/*** 基于Jackson的JSON转换工具类** @author 20026272* @version 2018/6/29 12:06*/
public class JacksonUtil {private JacksonUtil() {}private static final Logger LOGGER = LoggerFactory.getLogger(JacksonUtil.class);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());}/*** 对象 => json字符串** @param obj 源对象*/public static <T> String toJson(T obj) {String json = null;if (obj != null) {try {json = objectMapper.writeValueAsString(obj);} catch (JsonProcessingException e) {LOGGER.error("toJson: {}", e.toString());}}return json;}/*** json字符串 => 对象** @param json 源json串* @param clazz 对象类* @param 泛型*/ public static <T> T parse(String json, Class<T> clazz) {return parse(json, clazz, null);}/*** json字符串 => 对象** @param json 源json串* @param type 对象类型* @param 泛型*/ public static <T> T parse(String json, TypeReference<T> type) {return parse(json, null, type);}/*** json => 对象处理方法*
* 参数clazz和type必须一个为null,另一个不为null*
* 此方法不对外暴露,访问权限为private** @param json 源json串* @param clazz 对象类* @param type 对象类型* @param 泛型*/ private static <T> T parse(String json, Class<T> clazz, TypeReference<T> type) {T obj = null;if (!StringUtils.isEmpty(json)) {if (clazz != null) {try {obj = objectMapper.readValue(json, clazz);} catch (IOException e) {LOGGER.error("readValue: {}", e.toString());}} else {try {obj = objectMapper.readValue(json, type);} catch (IOException e) {LOGGER.error("readValue: {}", e.toString());}}}return obj;}
}
jackson配置详解
参考:Jackson用法并解决反序列化嵌套带引号的字符串对象_山鬼谣me的博客-CSDN博客_fastjson序列化转义双引号
//这个特性,决定了解析器是否将自动关闭那些不属于parser自己的输入源。
// 如果禁止,则调用应用不得不分别去关闭那些被用来创建parser的基础输入流InputStream和reader;
//默认是true
objectMapper.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, true);
//是否允许解析使用Java/C++ 样式的注释(包括'/'+'*' 和'//' 变量)
objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);//设置为true时,属性名称不带双引号
objectMapper.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, false);
//反序列化是是否允许属性名称不带双引号
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);//是否允许单引号来包住属性名称和字符串值
objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);//是否允许JSON字符串包含非引号控制字符(值小于32的ASCII字符,包含制表符和换行符)
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);//是否允许JSON整数以多个0开始
objectMapper.configure(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS, true);//null的属性不序列化
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);//按字母顺序排序属性,默认false
objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY,true);//是否以类名作为根元素,可以通过@JsonRootName来自定义根元素名称,默认false
objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE,true);//是否缩放排列输出,默认false
objectMapper.configure(SerializationFeature.INDENT_OUTPUT,false);//序列化Date日期时以timestamps输出,默认true
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,true);//序列化枚举是否以toString()来输出,默认false,即默认以name()来输出
objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true);//序列化枚举是否以ordinal()来输出,默认false
objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX,false);//序列化单元素数组时不以数组来输出,默认false
objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,true);//序列化Map时对key进行排序操作,默认false
objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS,true);//序列化char[]时以json数组输出,默认false
objectMapper.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS,true);//序列化BigDecimal时是输出原始数字还是科学计数,默认false,即以toPlainString()科学计数方式来输出
objectMapper.configure(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN,true);
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
