上篇文章Json工具Demo(一) 说了一些Json和Jackson框架的基本知识,以及Demo中需要用到的基本类。这篇文章主要写下json和java对象之间相互转换的工具类JacksonUtil.java和测试类Main.java。

如果是List<User>或者Map<String, User>使用toJsonWithRoot方法转换成json串,当用jsonToBeanByTypeReferenceWithRoot方法转换成Java Bean时,会导致该Bean为null。因此,需要使用一个新的类,如UserList或者UserMap类来实现,就可以避免这个问题。

使用下面的代码需要的依赖是:

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.8.5</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.8.5</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.8.5</version></dependency>

JacksonUtil

JacksonUtil.java

package org.fan.learn.utils;import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.IOException;
import java.util.Locale;
import java.util.Map;/*** Created by fan on 15-11-18.*/
public class JacksonUtil {private static final Logger LOGGER = LoggerFactory.getLogger(JacksonUtil.class);private static ObjectMapper mapper;public static synchronized ObjectMapper getMapperInstance(boolean createNew) {if (createNew) {return new ObjectMapper();} else if (mapper == null) {mapper = new ObjectMapper();//对象属性按字母顺序排列mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);//在反序列化时,如果类中没有对应的属性,不抛出JsonMappingException异常mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);//序列化时,如果对象的某属性为null,生成Json字符串时不包含这个null属性mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);mapper.setLocale(Locale.CHINA);}return mapper;}/*** 将java对象转换为字符串* @param param java 对象* @return json字符串*/public static String toJson(Object param){try {ObjectMapper objectMapper = JacksonUtil.getMapperInstance(false);objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false);String dataJson =  objectMapper.writeValueAsString(param);return dataJson;}catch (Exception e){LOGGER.warn("toJson",e);}return null;}/*** 将java对象为字符串 类名作为json的顶级属性* @param param java 对象* @returnjson字符串*/public static String toJsonWithRoot(Object param){try {ObjectMapper objectMapper = JacksonUtil.getMapperInstance(false);objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);String dataJson =  objectMapper.writeValueAsString(param);return dataJson;}catch (Exception e){LOGGER.warn("toJson",e);}return null;}/*** 将json字符串转换为java对象* @param json json字符串* @param cls java对象类型* @param <T>* @return*/public static <T> T jsonToBean(String json, Class<T> cls){try {ObjectMapper objectMapper = JacksonUtil.getMapperInstance(false);objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE,false);return objectMapper.readValue(json, cls);} catch (Exception e) {LOGGER.warn("jsonToBean",e);return null;}}/*** 将json字符串转换为java对象  ,解析字符串时,将类的名字或者别名作为顶级属性来解析* @param json json字符串* @param cls java对象类型* @param <T>* @return*/public static <T> T jsonToBeanWithRoot(String json, Class<T> cls){try {ObjectMapper objectMapper = JacksonUtil.getMapperInstance(false);objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);return objectMapper.readValue(json, cls);} catch (Exception e) {LOGGER.warn("jsonToBean",e);return null;}}/*** 将json字符串转换为java对象* @param json json字符串* @param typeReference 复杂的java对象类型* @param <T>* @return*/public static <T> T jsonToBeanByTypeReference(String json, TypeReference typeReference){try {ObjectMapper objectMapper = JacksonUtil.getMapperInstance(false);objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE,false);return objectMapper.readValue(json, typeReference);} catch (Exception e) {LOGGER.warn("jsonToBean",e);return null;}}/*** 将json字符串转换为java对象,解析字符串时,将类的名字或者别名作为顶级属性来解析* @param json json字符串* @param typeReference 复杂的java对象类型* @param <T>* @return*/public static <T> T jsonToBeanByTypeReferenceWithRoot(String json, TypeReference typeReference){try {ObjectMapper objectMapper = JacksonUtil.getMapperInstance(false);objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE,true);return objectMapper.readValue(json, typeReference);} catch (Exception e) {LOGGER.warn("jsonToBean",e);return null;}}/*** 从json字符串中读取出指定的节点** @param json* @param key* @return* @throws JsonProcessingException* @throws IOException*/public static JsonNode getValueFromJson(String json, String key) {ObjectMapper objectMapper = JacksonUtil.getMapperInstance(false);objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE,false);JsonNode node = null;try {node = objectMapper.readTree(json);return node.get(key);} catch (IOException e) {LOGGER.warn("getValueFromJson",e);return null;}}
}

Main测试

package org.fan.learn.json;import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.fan.learn.utils.JacksonUtil;import java.util.List;
import java.util.Map;/*** Created by fan on 15-11-18.*/
public class Main {public static void main(String[] args) {List<User> userList = Lists.newArrayList();String[] phone = {"15888888888", "15222222222"};Birthday birthday = new Birthday(2000,8,8);User user = new User("宝宝", -26, phone, birthday, true);User user1 = new User("fan", 25, phone, birthday, false);
/*        User user = new User();user.setName("fan");user.setAge(26);User user1 = new User();user1.setName("li");user1.setAge(25);*/userList.add(user);userList.add(user1);Map<String, User> userMap = Maps.newHashMap();userMap.put("user1", user);userMap.put("user2", user1);//会调用get方法String userString = JacksonUtil.toJson(user);//会调用无参构造函数,set方法User userJson = JacksonUtil.jsonToBean(userString, User.class);Map<String,String> userJsonMap = JacksonUtil.jsonToBean(userString, Map.class);System.out.println(userJsonMap);JsonNode name = JacksonUtil.getValueFromJson(userString, "NAME");JsonNode age = JacksonUtil.getValueFromJson(userString, "AGE");JsonNode phoneNode = JacksonUtil.getValueFromJson(userString, "PHONE");JsonNode birthdayNode = JacksonUtil.getValueFromJson(userString, "BIRTHDAY");JsonNode maleNode = JacksonUtil.getValueFromJson(userString, "MALE");String nameStr = name.toString();int ageInt = age.intValue();//List<String> phoneArr = phoneNode.findValuesAsText("PHONE");String[] phoneArr = new String[phoneNode.size()];for (int i = 0; i < phoneNode.size(); i++) {phoneArr[i] = phoneNode.get(i).toString();}Birthday birthdayObj = new Birthday();//会分别调用Birthday的3个setter方法birthdayObj.setYear(birthdayNode.get("year").intValue());birthdayObj.setMonth(birthdayNode.get("month").intValue());birthdayObj.setDay(birthdayNode.get("day").intValue());boolean male = maleNode.booleanValue();String userString2 = JacksonUtil.toJsonWithRoot(user);//使用这种内部数据将会是nullUser userJson2_1 = JacksonUtil.jsonToBean(userString2, User.class);User userJson2_2 = JacksonUtil.jsonToBeanWithRoot(userString2, User.class);String userListString = JacksonUtil.toJson(userList);List<User> userListJson = JacksonUtil.jsonToBeanByTypeReference(userListString,new TypeReference<List<User>>(){});String userListStringRoot = JacksonUtil.toJsonWithRoot(userList);//这种使用方法,得到的userListJsonRoot是nullList<User> userListJsonRoot = JacksonUtil.jsonToBeanByTypeReferenceWithRoot(userListStringRoot,new TypeReference<List<User>>(){});//使用UserList类UserList userListClass = new UserList();userListClass.setUserList(userList);String userListClassString = JacksonUtil.toJson(userListClass);UserList userListClassJason = JacksonUtil.jsonToBean(userListClassString, UserList.class);String userListClassStringRoot = JacksonUtil.toJsonWithRoot(userListClass);UserList userListClassJasonRoot = JacksonUtil.jsonToBeanWithRoot(userListClassStringRoot, UserList.class);String userMapString = JacksonUtil.toJson(userMap);Map<String, User> userMapJson = JacksonUtil.jsonToBeanByTypeReference(userMapString,new TypeReference<Map<String, User>>(){});String userMapStringRoot = JacksonUtil.toJsonWithRoot(userMap);//这种使用方法,得到的userMapJsonRoot是nullMap<String, User> userMapJsonRoot = JacksonUtil.jsonToBeanByTypeReferenceWithRoot(userMapStringRoot,new TypeReference<Map<String, User>>(){});//使用UserMap类UserMap userMapClass = new UserMap();userMapClass.setUserMap(userMap);String userMapClassString = JacksonUtil.toJson(userMapClass);UserMap userMapClassJson = JacksonUtil.jsonToBean(userMapClassString, UserMap.class);String userMapClassStringRoot = JacksonUtil.toJsonWithRoot(userMapClass);UserMap userMapClassJsonRoot = JacksonUtil.jsonToBeanWithRoot(userMapClassStringRoot, UserMap.class);}
}

代码分析及运行结果

1 关于Google guava
google guava所包含的内容远不止在Demo中使用的样子。由于本篇博文的重点在json,这里对guava不详细说明,给出链接资料:http://ifeve.com/google-guava/
在java 7之前,在构造新的泛型集合时要反复重新声明泛型。如下所示:

List<User> userList = new ArrayList<User>();

这样写太繁琐,因此guava推出了能够推断泛型的静态工厂方法:

List<User> userList = Lists.newArrayList();

2 json与java对象之间的转换
java对象转换成json,使用JacksonUtil.toJson ,这个方法调用过程中会调用java bean的get方法。如果java bean中不存在get方法也不影响转换的过程。
json转换成java对象,使用JacksonUtil.jsonToBean , 这个方法调用过程中首先会调用java bean的默认构造函数。如果java bean没有其他构造函数的话,编译器会自动添加默认构造函数。总之,默认构造函数必须要有,否则会报错。由json转java bean时也会调用setter方法。如果java bean中不存在set方法也不影响转换的过程。

        //会调用get方法String userString = JacksonUtil.toJson(user);//会调用无参构造函数,set方法User userJson = JacksonUtil.jsonToBean(userString, User.class);Map<String,String> userJsonMap = JacksonUtil.jsonToBean(userString, Map.class);

为了检验默认构造方法,setter,getter方法的调用,在POJO中有打印信息。
上面代码的执行结果,如下所示。

userString的内容:

{"AGE":-26,"BIRTHDAY":{"day":8,"month":8,"year":2000},"MALE":true,"NAME":"宝宝","PHONE":["15888888888","15222222222"]}

从上面可以看到,键值对的排序都是按照字母顺序排序的,而且还是大写的。原因如下:

            mapper = new ObjectMapper();//对象属性按字母顺序排列mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);

在创建POJO User.java时使用了注解。

    @JsonProperty("NAME")private String name;@JsonProperty("AGE")private int age;@JsonProperty("PHONE")private String[] phone;@JsonProperty("BIRTHDAY")private Birthday birthday;@JsonProperty("MALE")private boolean male;

userJson对象的内容

userJsonMap的内容

3 从json字符串中直接得到某一属性的值

        JsonNode name = JacksonUtil.getValueFromJson(userString, "NAME");JsonNode age = JacksonUtil.getValueFromJson(userString, "AGE");JsonNode phoneNode = JacksonUtil.getValueFromJson(userString, "PHONE");JsonNode birthdayNode = JacksonUtil.getValueFromJson(userString, "BIRTHDAY");JsonNode maleNode = JacksonUtil.getValueFromJson(userString, "MALE");String nameStr = name.toString();int ageInt = age.intValue();//List<String> phoneArr = phoneNode.findValuesAsText("PHONE");String[] phoneArr = new String[phoneNode.size()];for (int i = 0; i < phoneNode.size(); i++) {phoneArr[i] = phoneNode.get(i).toString();}Birthday birthdayObj = new Birthday();//会分别调用Birthday的3个setter方法birthdayObj.setYear(birthdayNode.get("year").intValue());birthdayObj.setMonth(birthdayNode.get("month").intValue());birthdayObj.setDay(birthdayNode.get("day").intValue());boolean male = maleNode.booleanValue();

4 在json字符串中显示根的名字

        String userString2 = JacksonUtil.toJsonWithRoot(user);//使用这种内部数据将会是nullUser userJson2_1 = JacksonUtil.jsonToBean(userString2, User.class);User userJson2_2 = JacksonUtil.jsonToBeanWithRoot(userString2, User.class);

userString2的内容如下所示:

{"FAN":{"AGE":-26,"BIRTHDAY":{"day":8,"month":8,"year":2000},"MALE":true,"NAME":"宝宝","PHONE":["15888888888","15222222222"]}}

之所以会显示头时因为,有注解:

@JsonRootName(value = "FAN")
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class User {
}

userJson2_1和userJson2_2的内容如下:

userJson2_1是null的,因为json串是有root的,重新解析时也要使用有root的。

5 关于集合List

        String userListString = JacksonUtil.toJson(userList);List<User> userListJson = JacksonUtil.jsonToBeanByTypeReference(userListString,new TypeReference<List<User>>(){});String userListStringRoot = JacksonUtil.toJsonWithRoot(userList);//这种使用方法,得到的userListJsonRoot是nullList<User> userListJsonRoot = JacksonUtil.jsonToBeanByTypeReferenceWithRoot(userListStringRoot,new TypeReference<List<User>>(){});

userListString的内容如下:

[{"AGE":-26,"BIRTHDAY":{"day":8,"month":8,"year":2000},"MALE":true,"NAME":"宝宝","PHONE":["15888888888","15222222222"]},{"AGE":25,"BIRTHDAY":{"day":8,"month":8,"year":2000},"MALE":false,"NAME":"fan","PHONE":["15888888888","15222222222"]}]

userListJson的内容:

但是有了root之后就有问题了:

因此对于集合最好不要使用jsonToBeanByTypeReference这种方式来将json转换成java bean。当遇到集合时,最好能新建一个集合的类。

//使用UserList类UserList userListClass = new UserList();userListClass.setUserList(userList);String userListClassString = JacksonUtil.toJson(userListClass);UserList userListClassJason = JacksonUtil.jsonToBean(userListClassString, UserList.class);String userListClassStringRoot = JacksonUtil.toJsonWithRoot(userListClass);UserList userListClassJasonRoot = JacksonUtil.jsonToBeanWithRoot(userListClassStringRoot, UserList.class);

userListClassString的内容如下:

{"USERLIST":[{"AGE":-26,"BIRTHDAY":{"day":8,"month":8,"year":2000},"MALE":true,"NAME":"宝宝","PHONE":["15888888888","15222222222"]},{"AGE":25,"BIRTHDAY":{"day":8,"month":8,"year":2000},"MALE":false,"NAME":"fan","PHONE":["15888888888","15222222222"]}]}

userListClassStringRoot的内容如下:

{"AAAAA":{"USERLIST":[{"AGE":-26,"BIRTHDAY":{"day":8,"month":8,"year":2000},"MALE":true,"NAME":"宝宝","PHONE":["15888888888","15222222222"]},{"AGE":25,"BIRTHDAY":{"day":8,"month":8,"year":2000},"MALE":false,"NAME":"fan","PHONE":["15888888888","15222222222"]}]}}

6 (1)map的情况跟list类似

        String userMapString = JacksonUtil.toJson(userMap);Map<String, User> userMapJson = JacksonUtil.jsonToBeanByTypeReference(userMapString,new TypeReference<Map<String, User>>(){});String userMapStringRoot = JacksonUtil.toJsonWithRoot(userMap);//这种使用方法,得到的userMapJsonRoot是nullMap<String, User> userMapJsonRoot = JacksonUtil.jsonToBeanByTypeReferenceWithRoot(userMapStringRoot,new TypeReference<Map<String, User>>(){});

userMapString的内容:

{"user2":{"AGE":25,"BIRTHDAY":{"day":8,"month":8,"year":2000},"MALE":false,"NAME":"fan","PHONE":["15888888888","15222222222"]},"user1":{"AGE":-26,"BIRTHDAY":{"day":8,"month":8,"year":2000},"MALE":true,"NAME":"宝宝","PHONE":["15888888888","15222222222"]}}

userMapStringRoot的内容:

{"HashMap":{"user2":{"AGE":25,"BIRTHDAY":{"day":8,"month":8,"year":2000},"MALE":false,"NAME":"fan","PHONE":["15888888888","15222222222"]},"user1":{"AGE":-26,"BIRTHDAY":{"day":8,"month":8,"year":2000},"MALE":true,"NAME":"宝宝","PHONE":["15888888888","15222222222"]}}}

(2)

//使用UserMap类UserMap userMapClass = new UserMap();userMapClass.setUserMap(userMap);String userMapClassString = JacksonUtil.toJson(userMapClass);UserMap userMapClassJson = JacksonUtil.jsonToBean(userMapClassString, UserMap.class);String userMapClassStringRoot = JacksonUtil.toJsonWithRoot(userMapClass);UserMap userMapClassJsonRoot = JacksonUtil.jsonToBeanWithRoot(userMapClassStringRoot, UserMap.class);

userMapClassString的内容:

{"USERMAP":{"user2":{"AGE":25,"BIRTHDAY":{"day":8,"month":8,"year":2000},"MALE":false,"NAME":"fan","PHONE":["15888888888","15222222222"]},"user1":{"AGE":-26,"BIRTHDAY":{"day":8,"month":8,"year":2000},"MALE":true,"NAME":"宝宝","PHONE":["15888888888","15222222222"]}}}

userMapClassStringRoot的内容:

{"BB":{"USERMAP":{"user2":{"AGE":25,"BIRTHDAY":{"day":8,"month":8,"year":2000},"MALE":false,"NAME":"fan","PHONE":["15888888888","15222222222"]},"user1":{"AGE":-26,"BIRTHDAY":{"day":8,"month":8,"year":2000},"MALE":true,"NAME":"宝宝","PHONE":["15888888888","15222222222"]}}}}

Json工具Demo(二)相关推荐

  1. DEMO程序连接到域控服务器( C#开发AD域控自动工具之二)

    搭建一个开发环境( C#开发AD域控自动工具之一) DEMO程序连接到域控服务器( C#开发AD域控自动工具之二) DEMO程序 创建一个用户( C#开发AD域控自动工具之三) 第一个需求,登陆名称绑 ...

  2. Code片段 : .properties属性文件操作工具类 JSON工具类

    摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢! "贵专" - 泥瓦匠 一.java.util.Properties API ...

  3. JS XML在线格式化、压缩、校验、XML转JSON工具-toolfk程序员工具网

    本文要推荐的[ToolFk]是一款程序员经常使用的线上免费测试工具箱,ToolFk 特色是专注于程序员日常的开发工具,不用安装任何软件,只要把内容贴上按一个执行按钮,就能获取到想要的内容结果.Tool ...

  4. Unity实用小工具或脚本——读写Json工具

    一.前言       在Unity中读写Json文件已经有非常好的工具,可以将Json文件和结构体数据进行相互转换,如图1所示,在Unity Asset Store中搜JSON.NET可以找到该插件, ...

  5. 9 个爱不释手的 JSON 工具

    点击关注上方"视学算法",设为"置顶或星标",第一时间送达技术干货. 众所周知,JSON让开发人员易于使用,又让机器易于解析和生成. JSON吸引了工具构建者的 ...

  6. java实用工具类——java处理对象转json工具类

    一.引言 json字符串现在是项目中很常用的了,尤其是在写接口返回数据一般都是json格式的.小编最近在看项目中,发现有多处地方用到了java对象转json,但是引用的jar包都是不统一的. 常见的有 ...

  7. Uber AVS 自动驾驶可视化工具(二)XVIZ之Overview

    Uber AVS 自动驾驶可视化工具 (二)XVIZ之Overview Overview Introduction Main Features XVIZ Protocol Specification ...

  8. SpringBoot的JSON工具类(java),用于前后端分离

    简介 JSON(JavaScript Object Notation, JS对象简谱)是一种轻量级的数据交换格式.它基于 ECMAScript(European Computer Manufactur ...

  9. JSON基础及Java的JSON工具类

    一.JSON基础 定义:JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式.它基于 ECMAScript (欧洲计算机协会制定的js规范)的 ...

最新文章

  1. Java--语言基础
  2. 删除文件夹中包含的子文件夹及文件
  3. Struts2中的ActionContext
  4. linux crontab定时任务详解
  5. 求到所有房子距离和最小的新房子
  6. java重载中this的作用_Java2:构造方法、方法重载和this关键字
  7. 如何在通达信中展现漂亮的港资持股曲线
  8. 我是明晃晃的开端(2017/4/17)
  9. 如何写一个脚本(附送一个脚本)
  10. 运动耳机什么牌子好、这五款是最值得推荐的运动耳机
  11. Windows各版本官方原版系统下载
  12. 新型冠状病毒传染模型SI、SIS、SIR、SEIR
  13. 回头再说说音乐--江湖笑 周华健
  14. 2021起重机作业 (Q)Q3起重机械指挥模拟考试题库及软件
  15. 机器视觉照明技术Machine Vision Light Technique
  16. Grating Period and Grating Constant(光栅周期与光栅常数)
  17. 功能强大的发卡网源码+支付接口超多
  18. SecureCRT常用命令分享 SecureCRT命令大全
  19. XRD物相检索的过程
  20. java redis管道_Redis的Java客户端Jedis的八种调用方式(事务、管道、分布式)介绍

热门文章

  1. 最新版Nginx安装教程来了,快来看看
  2. Leetcode-1598. 文件夹操作日志搜集器
  3. 跳转到wps查看文件
  4. 将字符串“I am a student.”逆序输出为“student. a am I”
  5. php中的 notice,php中对于NOTICE的问题排查,该注意什么?
  6. Lora技术- 码片/码元/数据速率以及空中时间计算
  7. 基于python的狗屁不通观后感生成器 2.0
  8. 一封来自大佬的密信待查收
  9. Lr预设(手机+电脑):复古巧克力色电影灯室棕褐色摄影Lightroom滤镜调色预设
  10. 使用word文件制作ftl模板文件总结(靠谱)