JSON转换工具类
上一期写的是关于时间的处理,这一期玩点有意思的,
第一部分 : 讲解基于jackson的POJO类与Json串互转的具体方法,
第二部分 : 讲解基于FastJson解析Json数据
第三部分 : 讲解基于Google Gson解析Json数据
第四部分 : 讲解基于以上写的工具类创建灵活的可扩展的键值存储表
第一部分 基于jackson的POJO类与Jason串互转
1. jackson简介
2. 引入依赖
添加依赖
jackson依赖
<!--jackson-->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
其它常用的工具包依赖
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-guava</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
3. 具体实现代码
package core.utils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.type.JavaType;
import org.codehaus.jackson.type.TypeReference;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.*;
public class JsonTools {
private static final Logger log = LoggerFactory.getLogger(JsonTools.class);
private static ObjectMapper objectMapper = new ObjectMapper();
static {
// 对象字段全部列入
objectMapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
// 取消默认转换timestamps形式
objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
// 忽略空bean转json的错误
objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
// 统一日期格式yyyy-MM-dd HH:mm:ss
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
// 忽略在json字符串中存在,但是在java对象中不存在对应属性的情况
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
/**
* object转Json字符串
*
* @param obj
* @param <T>
* @return
*/
public static <T> String obj2String(T obj) {
if (obj == null) {
return null;
}
try {
return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
} catch (Exception e) {
log.error("Parse object to String error "+ " obj : " + obj.toString(),e);
return null;
}
}
/**
* Object转json字符串并格式化美化
*
* @param obj
* @param <T>
* @return
*/
public static <T> String obj2StringPretty(T obj) {
if (obj == null) {
return null;
}
try {
return obj instanceof String ? (String) obj : objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
} catch (Exception e) {
log.error("Parse object to String error "+ " obj : " + obj.toString(),e);
return null;
}
}
/**
* string转object
*
* @param str json字符串
* @param clazz 被转对象class
* @param <T>
* @return
*/
public static <T> T string2Obj(String str, Class<T> clazz) {
if (StringUtils.isEmpty(str) || clazz == null) {
return null;
}
try {
return clazz.equals(String.class) ? (T) str : objectMapper.readValue(str, clazz);
} catch (IOException e) {
log.error("Parse object to String error "+ " str : " + str.toString() + " clazz : "+clazz.toString(),e);
return null;
}
}
/**
* string转object
*
* @param str json字符串
* @param typeReference 被转对象引用类型
* @param <T>
* @return
*/
public static <T> T string2ObjRef(String str, TypeReference<T> typeReference) {
if (StringUtils.isEmpty(str) || typeReference == null) {
return null;
}
try {
return (T) (typeReference.getType().equals(String.class) ? str : objectMapper.readValue(str, typeReference));
} catch (IOException e) {
log.error("Parse String to Object error " + " str : "+str.toString() + " typeReference : "+typeReference.toString() , e );
return null;
}
}
/**
* string转collection 用于转为集合对象
*
* @param str json字符串
* @param collectionClass 被转集合class
* @param elementClasses 被转集合中对象类型class
* @param <T>
* @return
*/
public static <T> T string2Collection(String str, Class<?> collectionClass, Class<?>... elementClasses) {
JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
try {
return objectMapper.readValue(str, javaType);
} catch (IOException e) {
log.error("Parse String to Collection error" + " str : "+str.toString() +
" collectionClass : "+collectionClass.toString() + " elementClasses : "+elementClasses.toString() , e);
return null;
}
}
/**
* 将对象以json写入流
* @param object
* @param out
* @throws IOException
*/
public static void writeJsonToSteam(Object object , OutputStream out) {
try {
objectMapper.writeValue( out , object);
} catch (IOException e) {
log.error("Parse String to Collection error" + " object: " +object.toString()+ " out: "+out , e);
}
}
/**
* 流的方式反序列化pojo对象
* @param input
* @param cls
* @param <T>
* @return
* @throws IOException
*/
public static <T>T inputSteamToObject (InputStream input , Class<T> cls ) {
try {
return objectMapper.readValue( input , cls);
} catch (IOException e) {
log.error("Parse String to Collection error" + " object: " +input.toString()+ " out: "+cls , e);
return null;
}
}
/**
* 流的方式反序列化集合
* @param input
* @param cls
* @param <T>
* @return
* @throws IOException
*/
public static <T>T inputSteamToObject (InputStream input , TypeReference<T> cls ) {
try {
return objectMapper.readValue( input , cls);
} catch (IOException e) {
log.error("Parse String to Collection error" + " object: " +input.toString()+ " out: "+cls , e);
return null;
}
}
static class Student {
//不JSON序列化年龄属性
@JsonIgnore
private Integer id;
@JsonProperty("NickName")
private String name;
private String sex;
private Integer grade;
//格式化日期属性
@JsonFormat(pattern = "yyyy-MM-DD HH:mi:ss")
private Date date;
private List<String> like;
private Map<String , Object> data;
public Student() {
}
public Student(Integer id, String name, String sex, Integer grade, Date date) {
this.id = id;
this.name = name;
this.sex = sex;
this.grade = grade;
this.date = date;
}
......
}
4. Test测试类
@Test
public void obj2StringAndString2Obj() {
Student student = new Student(1001, "xiaoming", "M", 80 ,new Date());
List<String> list = new ArrayList<>();
list.add("语文");
list.add("数学");
list.add("英语");
student.setLike( list );
Map< String , Object> map = new HashMap<>();
map.put("key1" , "key1");
map.put("key2" , "key2");
map.put("keyOfLike" , list);
student.setData( map );
System.out.println( "student : " +student);
String obj2StringPretty= JsonTools.obj2StringPretty(student);
System.out.println( "obj2StringPretty : " +obj2StringPretty);
Student string2Obj = JsonTools.string2Obj(obj2StringPretty, Student.class);
System.out.println(" string2Obj : "+string2Obj);
Map result = JsonTools.string2Obj(obj2StringPretty, Map.class);
System.out.println(" result : "+result);
}
##**执行结果:**
student : Student{id=1001, name='xiaoming', sex='M', grade=80, date=Sun Nov 18 00:41:57 CST 2018, like=[语文, 数学, 英语], data={key1=key1, key2=key2, keyOfLike=[语文, 数学, 英语]}}
obj2StringPretty : {
"sex" : "M",
"grade" : 80,
"date" : "2018-11-18 00:41:57",
"like" : [ "语文", "数学", "英语" ],
"data" : {
"key1" : "key1",
"key2" : "key2",
"keyOfLike" : [ "语文", "数学", "英语" ]
},
"NickName" : "xiaoming"
}
string2Obj : Student{id=null, name='xiaoming', sex='M', grade=80, date=Sun Nov 18 00:41:57 CST 2018, like=[语文, 数学, 英语], data={key1=key1, key2=key2, keyOfLike=[语文, 数学, 英语]}}
result : {sex=M, grade=80, date=2018-11-18 00:41:57, like=[语文, 数学, 英语], data={key1=key1, key2=key2, keyOfLike=[语文, 数学, 英语]}, NickName=xiaoming}
从以上的结果可以看出:
obj2StringPretty 中 name取得是 NickName 注解 @JsonProperty("NickName") 在 POJO转JSON生效
obj2StringPretty 中 date 为 "2018-11-18 00:41:57" 注解 @JsonFormat(pattern = "yyyy-MM-DD HH:mi:ss") 在 POJO转JSON生效
obj2StringPretty 中 没有 id 值 注解 @JsonIgnore 在 POJO转JSON生效
@Test
public void string2ObjRef() {
Student xiaoming = new Student(1001, "xiaoming", "M", 80 ,new Date());
List<String> list = new ArrayList<>();
list.add("语文");
list.add("数学");
list.add("英语");
xiaoming.setLike( list );
Map< String , Object> map = new HashMap<>();
map.put("key1" , "key1");
map.put("key2" , "key2");
map.put("keyOfLike" , list);
xiaoming.setData( map );
Student xiaowang = new Student(1002, "xiaowang", "F", 80 ,new Date());
xiaowang.setData( map );
List<Student> studentList = new ArrayList<>();
studentList.add(xiaoming);
studentList.add(xiaowang);
System.out.println( "studentList : " +studentList);
String obj2StringPretty = JsonTools.obj2StringPretty(studentList);
System.out.println( "obj2StringPretty : " +obj2StringPretty);
List<Student> string2ObjRef = JsonTools.string2ObjRef(obj2StringPretty, new TypeReference<List<Student>>() { });
System.out.println("string2ObjRef : " + string2ObjRef.toString());
}
##**执行结果:**
studentList : [Student{id=1001, name='xiaoming', sex='M', grade=80, date=Sun Nov 18 00:48:17 CST 2018, like=[语文, 数学, 英语], data={key1=key1, key2=key2, keyOfLike=[语文, 数学, 英语]}}, Student{id=1002, name='xiaowang', sex='F', grade=80, date=Sun Nov 18 00:48:17 CST 2018, like=null, data={key1=key1, key2=key2, keyOfLike=[语文, 数学, 英语]}}]
obj2StringPretty : [ {
"sex" : "M",
"grade" : 80,
"date" : "2018-11-18 00:48:17",
"like" : [ "语文", "数学", "英语" ],
"data" : {
"key1" : "key1",
"key2" : "key2",
"keyOfLike" : [ "语文", "数学", "英语" ]
},
"NickName" : "xiaoming"
}, {
"sex" : "F",
"grade" : 80,
"date" : "2018-11-18 00:48:17",
"data" : {
"key1" : "key1",
"key2" : "key2",
"keyOfLike" : [ "语文", "数学", "英语" ]
},
"NickName" : "xiaowang"
} ]
string2ObjRef : [Student{id=null, name='xiaoming', sex='M', grade=80, date=Sun Nov 18 00:48:17 CST 2018, like=[语文, 数学, 英语], data={key1=key1, key2=key2, keyOfLike=[语文, 数学, 英语]}}, Student{id=null, name='xiaowang', sex='F', grade=80, date=Sun Nov 18 00:48:17 CST 2018, like=null, data={key1=key1, key2=key2, keyOfLike=[语文, 数学, 英语]}}]
@Test
public void string2Collection() {
Student xiaoming = new Student(1001, "xiaoming", "M", 80 ,new Date());
List<String> list = new ArrayList<>();
list.add("语文");
list.add("数学");
list.add("英语");
xiaoming.setLike( list );
Map< String , Object> map = new HashMap<>();
map.put("key1" , "key1");
map.put("key2" , "key2");
map.put("keyOfLike" , list);
xiaoming.setData( map );
Student xiaobai = new Student(1002, "xiaobai", "F", 80 ,new Date());
xiaobai.setData( map );
List<Student> studentList = new ArrayList<>();
studentList.add(xiaoming);
studentList.add(xiaobai);
String studentListStr = JsonTools.obj2StringPretty(studentList);
//List<Student> studentListObj = JsonTools.string2ObjRef(studentListStr, new TypeReference<List<Student>>(){});
// 依次传入集合以及集合中对象类型的class
List<Student> studentListObj = JsonTools.string2Collection(studentListStr, List.class, Student.class);
System.out.println(studentListObj.toString());
}
##**执行结果:**
studentListObj [Student{id=null, name='xiaoming', sex='M', grade=80, date=Sun Nov 18 00:54:02 CST 2018, like=[语文, 数学, 英语], data={key1=key1, key2=key2, keyOfLike=[语文, 数学, 英语]}}, Student{id=null, name='xiaobai', sex='F', grade=80, date=Sun Nov 18 00:54:02 CST 2018, like=null, data={key1=key1, key2=key2, keyOfLike=[语文, 数学, 英语]}}]
5. jackson 处理XML请看 jackson处理XML
第二部分 基于FastJson解析Json数据
1. FastJson简介
fastjson 是一个性能极好的用 Java 语言实现的 JSON 解析器和生成器,来自阿里巴巴的工程师开发。
主要特点:
快速FAST (比其它任何基于Java的解析器和生成器更快,包括jackson)
强大(支持普通JDK类包括任意Java Bean Class、Collection、Map、Date或enum)
零依赖(没有依赖其它任何类库除了JDK)
2. 代码实现
还是基于上面的pojo类
@Test
public void obj2StringAndString2Obj() {
Student student = new Student(1001, "xiaoming", "M", 80 ,new Date());
List<String> list = new ArrayList<>();
list.add("语文");
list.add("数学");
list.add("英语");
student.setLike( list );
Map< String , Object> map = new HashMap<>();
map.put("key1" , "key1");
map.put("key2" , "key2");
map.put("keyOfLike" , list);
student.setData( map );
System.out.println( "student : " +student);
// String obj2StringPretty= JsonTools.obj2StringPretty(student);
// System.out.println( "obj2StringPretty : " +obj2StringPretty);
//
// Student string2Obj = JsonTools.string2Obj(obj2StringPretty, Student.class);
// System.out.println(" string2Obj : "+string2Obj);
// Map result = JsonTools.string2Obj(obj2StringPretty, Map.class);
// System.out.println(" result : "+result);
String jsonString = JSON.toJSONString(student);
System.out.println( "jsonString : " +jsonString);
Student parseObject = JSON.parseObject(jsonString, Student.class);
System.out.println(" parseObject : "+parseObject);
Map result = JSON.parseObject(jsonString, Map.class);
System.out.println(" result : "+result);
}
##**执行结果:**
student : Student{id=1001, name='xiaoming', sex='M', grade=80, date=Sun Nov 18 01:06:26 CST 2018, like=[语文, 数学, 英语], data={key1=key1, key2=key2, keyOfLike=[语文, 数学, 英语]}}
jsonString : {"data":{"key1":"key1","key2":"key2","keyOfLike":["语文","数学","英语"]},"date":1542474386634,"grade":80,"id":1001,"like":["语文","数学","英语"],"name":"xiaoming","sex":"M"}
parseObject : Student{id=1001, name='xiaoming', sex='M', grade=80, date=Sun Nov 18 01:06:26 CST 2018, like=[语文, 数学, 英语], data={key1=key1, key2=key2, keyOfLike=["语文","数学","英语"]}}
result : {date=1542474386634, data={"key1":"key1","key2":"key2","keyOfLike":["语文","数学","英语"]}, like=["语文","数学","英语"], grade=80, sex=M, name=xiaoming, id=1001}
从FastJson解析Json数据的结果可以看出 , 之前POJO类中加入的所有注解对FastJson解析为JSON的过程中并没有影响
@Test
public void string2ObjRef() {
Student xiaoming = new Student(1001, "xiaoming", "M", 80 ,new Date());
List<String> list = new ArrayList<>();
list.add("语文");
list.add("数学");
list.add("英语");
xiaoming.setLike( list );
Map< String , Object> map = new HashMap<>();
map.put("key1" , "key1");
map.put("key2" , "key2");
map.put("keyOfLike" , list);
xiaoming.setData( map );
Student xiaowang = new Student(1002, "xiaowang", "F", 80 ,new Date());
xiaowang.setData( map );
List<Student> studentList = new ArrayList<>();
studentList.add(xiaoming);
studentList.add(xiaowang);
// System.out.println( "studentList : " +studentList);
// String obj2StringPretty = JsonTools.obj2StringPretty(studentList);
// System.out.println( "obj2StringPretty : " +obj2StringPretty);
// List<Student> string2ObjRef = JsonTools.string2ObjRef(obj2StringPretty, new TypeReference<List<Student>>() { });
// System.out.println("string2ObjRef : " + string2ObjRef.toString());
String jsonString = JSON.toJSONString(studentList);
System.out.println( "jsonString : " +jsonString);
List<Student> string2ObjRef=JSON.parseArray(jsonString, Student.class);
System.out.println("string2ObjRef : " + string2ObjRef.toString());
}
##**执行结果:**
jsonString : [{"data":{"key1":"key1","key2":"key2","keyOfLike":["语文","数学","英语"]},"date":1542475554692,"grade":80,"id":1001,"like":["语文","数学","英语"],"name":"xiaoming","sex":"M"},{"data":{"$ref":"$[0].data"},"date":1542475554692,"grade":80,"id":1002,"name":"xiaowang","sex":"F"}]
string2ObjRef : [Student{id=1001, name='xiaoming', sex='M', grade=80, date=Sun Nov 18 01:25:54 CST 2018, like=[语文, 数学, 英语], data={key1=key1, key2=key2, keyOfLike=["语文","数学","英语"]}}, Student{id=1002, name='xiaowang', sex='F', grade=80, date=Sun Nov 18 01:25:54 CST 2018, like=null, data={$ref=$[0].data}}]
3. FastJson还有如下方法,部分上文已有测试案例
1 、生成Json:
JavaBean、List<JavaBean>、List<String>、List<Map<String,Object>>
String jsonString = JSON.toJSONString(obj);
2、解析Json:
(1)JavaBean
Class class= JSON.parseObject(jsonString, Class.class);
(2)List
List<Class> class=JSON.parseArray((jsonString, Class.class);
(3)List
List<String> listString = JSON.parseArray(jsonString, String.class);
(4)List<Map<String,Object>>
List<Map<String, Object>> listMap = JSON.parseObject(jsonString, new TypeReference<List<Map<String,Object>>>(){});
3 .获取json中指定数据:
现有这样的json数据:
{"totalRecords":2615,
"result":{"code":"200","status":"success"},
"list":[{"unuAbnId":"0bcd930f-014c-1000-e003-5f160a0d0114",
"entNo":"1c2e4ca8-00fa-1000-e000-74590a76bf0f",
"regNO":"442000600169663",
"entName":"x",
"entType":"9910 ",
"speCause":"3",
"abnTime":"Mar 13, 2015 12:00:00 AM",
"decOrg":"442020",
"entNameUrl":"<a href=\".. ",
"auditingFileNo":"15000684990326",
"abnormalID":"fd74013d-014b-1000-e00a-72970a0d0114"},{...},{...},...],
"pageNo":1,
"pageSize":8,
"url":"main/abnInfoPage",
"selList":[{"unuAbnId":"0bcd930f-014c-1000-e003-5f0f0a0d0114",
"entNo":"16da9629-0131-1000-e005-3effc0a803a8",
"regNO":"442000602187424",
"entName":"x",
"entType":"9910 ",
"speCause":"3",
"abnTime":"Mar 13, 2015 12:00:00 AM",
"decOrg":"442020",
"entNameUrl":"<a href=\"..\">",
"auditingFileNo":"15000684990319",
"abnormalID":"fd74013d-014b-1000-e00a-72970a0d0114"},{...},{...},...],
"topPageNo":1,
"totalPages":327,
"previousPageNo":0,
"nextPageNo":2,
"bottomPageNo":327
}
其中list含有2615条数据,selList含有8条数据,目标是提取selList中entNameUrl的链接(不含a href=)
外层是JSONObject,里面的list和selList是JSONArrary,再里面是JSONObject。其中的result也是JSONObject
JSONObject jsonObj = JSON.parseObject(rawText);
JSONArray result = jsonObj.getJSONArray("selList");
List<Link> links= JSON.parseArray(result.toJSONString(),Link.class);
其中Link类中要有entNameUrl这个属性,并且setter和getter方法。
在setter方法中可以进一步进行处理
public void setEntNameUrl(String entNameUrl) {
this.entNameUrl =Html.create(entNameUrl).links().get();
}
这里使用了自定方法,其功能就是取出字符串中的链接。
Link类中可以包含abnTime、entName、regNO等属性和对应的getter和setter方法,FastJson能自动映射。
通过下面的方法也可以处理:
JSONObject jsonObj = new JSONObject(rawText);
JSONArray jsonArray = result .getJSONArray("selList");
for (int i = 0; i < jsonArray.length; i++) {
}
此处转载自 : https://blog.youkuaiyun.com/G1Apassz/article/details/44456293
4. FastJson使用的扩展
java中,通过FastJson对海量数据的Json文件,边读取边解析
fastjson(七)处理超大对象和超大JSON文本
第三部分 基于Google Gson解析Json数据
1. Google Gson简介
Gson类:解析json的最基础的工具类
JsonParser类:解析器来解析JSON到JsonElements的解析树
JsonElement类:一个类代表的JSON元素
JsonObject类:JSON对象类型
JsonArray类:JsonObject数组
TypeToken类:用于创建type,比如泛型List<?>
maven 依赖:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.7</version>
</dependency>
具体测试用例看链接:
Google Gson的使用方法及JSON 技术对比