项目中需要用jackson替换fastjson,因为自己对json了解不是很多,所以通过看视频与相关文章写了一个通用的jackson工具类,这篇文章是自己做一个总结
1.序列化
序列化是指将对象转化成字节序列,方便持久化存储到磁盘,避免程序运行结束后对象就从内存里消失,另外变换成字节序列也更便于网络运输和传播
2 反序列化
反序列化就是指将字节序列转化成对象
对于Json 框架来说、想要把一个 Java 对象转换成字符串、有两种选择:
FastJson 和 Jackson 在把对象序列化成 json 字符串的时候、是通过遍历该类中所有 getter 方法进行的。Gson并不是这么做的,他是通过反射遍历该类中的所有属性,并把其值序列化成json。
jackson主要用到的工具类是ObjectMapper,使用ObjectMapper可以基本解决序列化问题
public class JacksonUtil {
private static ObjectMapper objectMapper =new ObjectMapper();
/** 默认日期时间格式 */
public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
/** 默认日期格式 */
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
/** 默认时间格式 */
public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
static {//初始化
//设置date属性
SimpleDateFormat dateFormat =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
objectMapper.setDateFormat(dateFormat);
objectMapper.setTimeZone(TimeZone.getTimeZone("GTM+8"));
//当JSON数据的属性多于java对象属性时,会抛异常,这时,需要通过配置Jackson的Feature使能可以让你忽略那些多余的属性
objectMapper.configure(
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//设置LocalDateTime,LocalDate,LocalTime
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
objectMapper.registerModule(javaTimeModule);
objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
//空指针不报错
objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
//未知错误不报错
objectMapper.disable(SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS);
//支持null和空串
objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
//下边这些配置根据自己项目实际情况加,反正我是都用到了
//字符串中允许单引号
objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES,true);
//表示字符串中也可以无引号
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES,true);
//允许支持JSON数组中“缺失”值,数组中缺失了值表示两个逗号之间,啥都没有,形如这样[value1, , value3]。
objectMapper.configure(JsonParser.Feature.ALLOW_MISSING_VALUES,true);
//允许像00001这样的“数字”出现(而不报错)
objectMapper.configure(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS,true);
//允许**反斜杠**转义任何字符
objectMapper.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER,true);
//允许/* */或者//这种类型的注释出现。
objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS,true);
//支持Yaml格式的的注释,也就是#形式的注释语法。形如 {"table#abd":"test"}
objectMapper.configure(JsonParser.Feature.ALLOW_YAML_COMMENTS,true);
//支持结尾逗号{"name":"小明","age": "18",}
objectMapper.configure(JsonParser.Feature.ALLOW_TRAILING_COMMA, true);
}
}
public static String toJSONString(Object o) {
String json =null;
try {
json =objectMapper.writeValueAsString(o);
}catch (JsonProcessingException e){
System.out.println(e.getMessage());
}
return json;
}
public static <T> T parseObject(Object text,Class<T> clazz) {
if (text==null){
return null;
}else {
T json = null;
try {
if (text instanceof JsonNode){
T pojo = objectMapper.convertValue(text,clazz);
return pojo;
}
if (text instanceof ArrayNode){
T pojo = objectMapper.convertValue(text,clazz);
return pojo;
}
if (text instanceof ObjectNode){
T pojo = objectMapper.convertValue(text,clazz);
return pojo;
}
if (text instanceof String){
String resut =text.toString();
json = objectMapper.readValue(resut, clazz);
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
return json;
}
}
json转数组 其实跟上边 3的用法差不多,都可以达到同样的效果,但是因为要模仿fastjson的方法,这样改起来会方便一点
public static <T> List<T> parseArray(String text, Class<T> clazz) {
if (text==null){
return null;
}else {
try {
return objectMapper.readValue(text, objectMapper.getTypeFactory().constructParametricType(List.class, clazz));
} catch (Exception e) {
System.out.println(e.getMessage());
}
return null;
}
}
jsonNode 相当于fastjson的JSONObject,不过jsonNode侧重于读取,并不支持写入操作
public static JsonNode parseObject(String text){
JsonNode jsonNode = null;
try {
jsonNode = objectMapper.readTree(text);
if (jsonNode.isNull()){
return null;
}
}catch (IOException e){
System.out.println(e.getMessage());
}
return jsonNode;
}
public static void main(String[] args) {
Map<String,Object> map1 =new HashMap<>();
map1.put("小明","男");
map1.put("test",map);
String jason =JacksonUtil.toJSONString(map1);
JsonNode jsonNode =JacksonUtil.parseObject(jason);
jsonNode.asText();//类似于fastjson中的getString(),一定不要用toString,本身就是字符串了,在toString会""""
jsonNode.isArray();//判断是否是数组
jsonNode.get("key");//获取json字符串中的对象属性
jsonNode.elements();//如果在判断为数组的前提下,可以进行遍历(与ArrayNode.elements()一样)
}
//objectNode一般用于写操作,可以用于转换成ArrayNode,ArrayNode相当于fastjson的JSONArray
public static ObjectNode objectNode(){
ObjectNode jsonNode = null;
jsonNode = objectMapper.createObjectNode();
return jsonNode;
}
public static void main(String[] args) {
ObjectNode newNode =objectMapper.createObjectNode();
newNode.put("list", String.valueOf(response));//新增基本数据类型
newNode.putPOJO("list",response);//新增object
ArrayNode arrayNode= newNode.putArray("ada");//创建ArrayNode
}
ArrayNode arrayNode =JsonNodeFactory.instance.arrayNode();
//必须赋予key值
ArrayNode arrayNode =objectNode.putArray("key");
public static void main(String[] args) {
ArrayNode arrayNode =JsonNodeFactory.instance.arrayNode();
arrayNode.addPOJO("dad");//添加Object
arrayNode.add();//添加基本数据类型
Iterator<JsonNode> iterator =arrayNode.elements();//迭代器遍历数组
arrayNode.size();//获取数组长度
}
ArrayNode,ObjectNode,jsonNode的具体用法就不一一细说了,大家可以在搜其他的文章获取具体用法
两者都是为对象属性定义一个别名,区别在于@JsonAlias是在反序列化时根据别名进行属性映射,而@JsonProperty是序列化和反序列化都会进行映射
@Getter
@Setter
public class User {
@JsonAlias(value = "nm")
private String name;
private Integer age;
}
通过 @JacksonInject 注解可以在 Jackson 反序列化的时候为空值字段动态赋值,当反序列化的对应属性值不存在时,可通过该注解为其动态设置值。
@Getter
@Setter
public class User {
@JacksonInject(value = "dynamic")
private String name;
private Integer age;
}
在序列化、反序列化时会忽略被该注解标记的属性。
@Getter
@Setter
public class User {
@JsonIgnore
private String name;
private String age;
}
1.JSONObject的toString并不等同于JsonNode的toString,fastjson的toSting是序列化过的,与toJSONString一样,所以toString就意味着是序列化了,JsonNode只是单纯的变字符串。