浅谈JackSon的几种用法
时光时光慢一点 人气:0这篇文章主要介绍了浅谈JackSon的几种用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
JackSon介绍
本文使用的JackSon版本为2.9.6。
JackSon是解析JSON和XML的一个框架,优点是简单易用,性能较高。
JackSon处理JSON的方式
JackSon提供了三种JSON的处理方式。分别是数据绑定,树模型,流式API。下面会分别介绍这三种方式。
JackSon数据绑定
数据绑定用于JSON转化,可以将JSON与POJO对象进行转化。数据绑定有两种,简单数据绑定和完整数据绑定。
完整数据绑定
package com.xymxyg.json; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; /** * @author guangsheng.tang * 下面是最常用的场景,将json字符串映射为对象,或者是将对象转化为json字符串。这是完整数据绑定。 缺点:这种方法十分方便,但是扩展性不强,增加一个字段便要修改POJO对象,这个操作有一定风险性。并且解析的时候,如果json缺少POJO中的某字段,映射出的对象对应值默认为null,直接使用有一定风险。如果json对象多了某一字段,解析过程中会抛出UnrecognizedPropertyException异常。并且如果json较为复杂的话,POJO对象会显得特别臃肿。 */ public class CompleteDataBind { public static void main(String[] args) throws IOException { String s = "{\"id\": 1,\"name\": \"小明\",\"array\": [\"1\", \"2\"]}"; ObjectMapper mapper = new ObjectMapper(); //Json映射为对象 Student student = mapper.readValue(s, Student.class); //对象转化为Json String json = mapper.writeValueAsString(student); System.out.println(json); System.out.println(student.toString()); } }
package com.xymxyg.json; /** * @author guangsheng.tang */ public class Student { private int id; private String name; private String sex; private ArrayList<String> array; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public ArrayList<String> getArray() { return array; } public void setArray(ArrayList<String> array) { this.array = array; } @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", sex='" + sex + '\'' + ", array=" + Arrays.toString(array.toArray()) + '}'; } }
简单数据绑定
简单数据绑定就是将json字符串映射为java核心的数据类型。
json类型 | Java类型 |
---|---|
object | LinkedHashMap |
array | ArrayList |
string | String |
number | Integer,Long,Double |
true|false | Boolean |
null | null |
下面演示一个例子,将json转化为一个Map。通过Map来读取。
package com.xymxyg.json; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Map; /** * @author guangsheng.tang * 简单数据绑定的示例,不用POJO对象,直接映射为一个Map,然后从Map中获取。 */ public class SimpleDataBind { public static void main(String[] args) throws IOException { Map<String, Object> map = new HashMap<>(16); String s = "{\"id\": 1,\"name\": \"小明\",\"array\": [\"1\", \"2\"]," + "\"test\":\"I'm test\",\"base\": {\"major\": \"物联网\",\"class\": \"3\"}}"; ObjectMapper mapper = new ObjectMapper(); map = mapper.readValue(s, map.getClass()); //获取id Integer studentId = (Integer) map.get("id"); System.out.println(studentId); //获取数据 ArrayList list = (ArrayList) map.get("array"); System.out.println(Arrays.toString(list.toArray())); //新增加的字段可以很方便的处理 String test = (String) map.get("test"); System.out.println(test); //不存在的返回null String notExist = (String) map.get("notExist"); System.out.println(notExist); //嵌套的对象获取 Map base = (Map) map.get("base"); String major = (String) base.get("major"); System.out.println(major); } }
树模型
针对JackSon的树模型结构,我下面写了一个比较完善的例子。同样Java树模型有优点,也有缺点。
package com.xymxyg.json; import com.fasterxml.jackson.core.JsonPointer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.NullNode; import com.fasterxml.jackson.databind.node.ObjectNode; import java.io.IOException; /** * @author guangsheng.tang * JackSon树模型结构,可以通过get,JsonPointer等进行操作,适合用来获取大Json中的字段,比较灵活。缺点是如果需要获取的内容较多, * 会显得比较繁琐。 */ public class TreeModel { public static void main(String[] args) throws IOException { ObjectMapper mapper = new ObjectMapper(); //以下是对象转化为Json JsonNode root = mapper.createObjectNode(); ((ObjectNode) root).putArray("array"); ArrayNode arrayNode = (ArrayNode) root.get("array"); ((ArrayNode) arrayNode).add("args1"); ((ArrayNode) arrayNode).add("args2"); ((ObjectNode) root).put("name", "小红"); String json = mapper.writeValueAsString(root); System.out.println("使用树型模型构建的json:"+json); //以下是树模型的解析Json String s = "{\"id\": 1,\"name\": \"小明\",\"array\": [\"1\", \"2\"]," + "\"test\":\"I'm test\",\"nullNode\":null,\"base\": {\"major\": \"物联网\",\"class\": \"3\"}}"; //读取rootNode JsonNode rootNode = mapper.readTree(s); //通过path获取 System.out.println("通过path获取值:" + rootNode.path("name").asText()); //通过JsonPointer可以直接按照路径获取 JsonPointer pointer = JsonPointer.valueOf("/base/major"); JsonNode node = rootNode.at(pointer); System.out.println("通过at获取值:" + node.asText()); //通过get可以取对应的value JsonNode classNode = rootNode.get("base"); System.out.println("通过get获取值:" + classNode.get("major").asText()); //获取数组的值 System.out.print("获取数组的值:"); JsonNode arrayNode2 = rootNode.get("array"); for (int i = 0; i < arrayNode2.size(); i++) { System.out.print(arrayNode2.get(i).asText()+" "); } System.out.println(); //path和get方法看起来很相似,其实他们的细节不同,get方法取不存在的值的时候,会返回null。而path方法会 //返回一个"missing node",该"missing node"的isMissingNode方法返回值为true,如果调用该node的asText方法的话, // 结果是一个空字符串。 System.out.println("get方法取不存在的节点,返回null:" + (rootNode.get("notExist") == null)); JsonNode notExistNode = rootNode.path("notExist"); System.out.println("notExistNode的value:" + notExistNode.asText()); System.out.println("isMissingNode方法返回true:" + notExistNode.isMissingNode()); //当key存在,而value为null的时候,get和path都会返回一个NullNode节点。 System.out.println(rootNode.get("nullNode") instanceof NullNode); System.out.println(rootNode.path("nullNode") instanceof NullNode); } }
流式API
流式API是一套比较底层的API,速度快,但是使用起来特别麻烦。它主要是有两个核心类,一个是JsonGenerator,用来生成json,另一个是JsonParser,用来读取json内容。话不多说,直接上代码演示。
package com.xymxyg.json; import com.fasterxml.jackson.core.*; import java.io.File; import java.io.FileInputStream; import java.io.IOException; /** * @author guangsheng.tang * JsonParser和Generator的优点是速度快,缺点是写起来真的很复杂。 */ public class StreamApi { public static void main(String[] args) throws IOException { JsonFactory factory = new JsonFactory(); String s = "{\"id\": 1,\"name\": \"小明\",\"array\": [\"1\", \"2\"]," + "\"test\":\"I'm test\",\"nullNode\":null,\"base\": {\"major\": \"物联网\",\"class\": \"3\"}}"; //这里就举一个比较简单的例子,Generator的用法就是一个一个write即可。 File file = new File("/json.txt"); JsonGenerator jsonGenerator = factory.createGenerator(file, JsonEncoding.UTF8); //对象开始 jsonGenerator.writeStartObject(); //写入一个键值对 jsonGenerator.writeStringField("name", "小光"); //对象结束 jsonGenerator.writeEndObject(); //关闭jsonGenerator jsonGenerator.close(); //读取刚刚写入的json FileInputStream inputStream = new FileInputStream(file); int i = 0; final int SIZE = 1024; byte[] buf = new byte[SIZE]; StringBuilder sb = new StringBuilder(); while ((i = inputStream.read(buf)) != -1) { System.out.println(new String(buf,0,i)); } inputStream.close(); //JsonParser解析的时候,思路是把json字符串根据边界符分割为若干个JsonToken,这个JsonToken是一个枚举类型。 //下面这个小例子,可以看出JsonToken是如何划分类型的。 JsonParser parser = factory.createParser(s); while (!parser.isClosed()){ JsonToken token = parser.currentToken(); System.out.println(token); parser.nextToken(); } JsonParser jsonParser = factory.createParser(s); //下面是一个解析的实例 while (!jsonParser.isClosed()) { JsonToken token = jsonParser.nextToken(); if (JsonToken.FIELD_NAME.equals(token)) { String currentName = jsonParser.currentName(); token = jsonParser.nextToken(); if ("id".equals(currentName)) { System.out.println("id:" + jsonParser.getValueAsInt()); } else if ("name".equals(currentName)) { System.out.println("name:" + jsonParser.getValueAsString()); } else if ("array".equals(currentName)) { token = jsonParser.nextToken(); while (!JsonToken.END_ARRAY.equals(token)) { System.out.println("array:" + jsonParser.getValueAsString()); token = jsonParser.nextToken(); } } } } } }
JackSon的常用注解
JackSon提供了一些的注解,可以用在类上或者是在字段上。通常是数据绑定的时候使用。下面几个是最常用的几个
@JsonInclude(Include.NON_EMPTY)
仅在属性不为空时序列化此字段,对于字符串,即null或空字符串
@JsonIgnore
序列化时忽略此字段
@JsonProperty(value = “user_name”)
指定序列化时的字段名,默认使用属性名
总结
JackSon使用起来还是十分方便的,提供的功能也很多,在使用的时候,需要结合自己的业务场景,选择合适的解析方式。
参考资料
http://blog.lifw.org/post/63088058v
https://www.yiibai.com/jackson/
加载全部内容