博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
jackson - jackson简述
阅读量:5334 次
发布时间:2019-06-15

本文共 18861 字,大约阅读时间需要 62 分钟。

概述

Jackson框架是基于Java平台的一套数据处理工具,被称为“最好的Java Json解析器”。 

Jackson框架包含了3个核心库:streaming,databind,annotations.Jackson还包含了其它数据处理类库,此外不作说明。
Jackson版本: 1.x (目前版本从1.1~1.9)与2.x。1.x与2.x从包的命名上可以看出来,1.x的类库中,包命名以:org.codehaus.jackson.xxx开头,而2.x类库中包命令:com.fastxml.jackson.xxx开头

Jackson Home Page:

Jackson Wiki:
Jackson doc: 
Jackson Download Page:

 

准备工作

本文所有程序都基于JDK1.7,依赖jackon的三个核心类库:

jackson-core-2.5.3.jar
jackson-annotations-2.5.3.jar
jackson-databind-2.5.3.jar

 

Jackson处理Json

Jackson提供了三种可选的Json处理方法:流式API(Streaming API) 、树模型(Tree Model)、数据绑定(Data Binding)。从使用角度来看,比较一下这三种处理Json的方式的特性:

Streaming API:是效率最高的处理方式(开销低、读写速度快,但程序编写复杂度高)

Tree Model:是最灵活的处理方式
Data Binding:是最常用的处理方式

下面我们通过例子程序分别使用DataBinding,TreeModel,Streaming的方式来创建和解析Json字符串

 

1.DataBinding处理Json

Jackson支持Java对象与Json之间的相互转化。java对象序列化为json字符串,json字符串也可以反序列化为相同的java对象。
 
(1)java对象转化成json:
Province.java
package com.jackson.json.databinding; public class Province {    public String name;    public int population;    public String[] city;    }
Country.java
 
package com.jackson.json.databinding; import java.util.ArrayList;import java.util.Arrays;import java.util.Date;import java.util.HashMap;import java.util.List;import java.util.Map; public class Country {    // 注意:被序列化的bean的private属性字段需要创建getter方法或者属性字段应该为public    private String country_id;    private Date birthDate;    private List
nation = new ArrayList
(); private String[] lakes; private List
provinces = new ArrayList
(); private Map
traffic = new HashMap
(); public Country() { // TODO Auto-generated constructor stub } public Country(String countryId) { this.country_id = countryId; } public String getCountry_id() { return country_id; } public void setCountry_id(String country_id) { this.country_id = country_id; } public Date getBirthDate() { return birthDate; } public void setBirthDate(Date birthDate) { this.birthDate = birthDate; } public List
getNation() { return nation; } public void setNation(List
nation) { this.nation = nation; } public String[] getLakes() { return lakes; } public void setLakes(String[] lakes) { this.lakes = lakes; } public Integer get(String key) { return traffic.get(key); } public Map
getTraffic() { return traffic; } public void setTraffic(Map
traffic) { this.traffic = traffic; } public void addTraffic(String key, Integer value) { traffic.put(key, value); } public List
getProvinces() { return provinces; } public void setProvinces(List
provinces) { this.provinces = provinces; } @Override public String toString() { return "Country [country_id=" + country_id + ", birthDate=" + birthDate + ", nation=" + nation + ", lakes=" + Arrays.toString(lakes) + ", province=" + provinces + ", traffic=" + traffic + "]"; } }

JavaBeanSerializeToJson.java

package com.jackson.json.databinding; import java.io.File;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.List; import com.fasterxml.jackson.annotation.JsonInclude.Include;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.SerializationFeature; public class JavaBeanSerializeToJson {     public static void convert() throws Exception {        // 使用ObjectMapper来转化对象为Json        ObjectMapper mapper = new ObjectMapper();        // 添加功能,让时间格式更具有可读性        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");        mapper.setDateFormat(dateFormat);         Country country = new Country("China");        country.setBirthDate(dateFormat.parse("1949-10-01"));        country.setLakes(new String[] { "Qinghai Lake", "Poyang Lake",                "Dongting Lake", "Taihu Lake" });         List
nation = new ArrayList
(); nation.add("Han"); nation.add("Meng"); nation.add("Hui"); nation.add("WeiWuEr"); nation.add("Zang"); country.setNation(nation); Province province = new Province(); province.name = "Shanxi"; province.population = 37751200; Province province2 = new Province(); province2.name = "ZheJiang"; province2.population = 55080000; List
provinces = new ArrayList
(); provinces.add(province); provinces.add(province2); country.setProvinces(provinces); country.addTraffic("Train(KM)", 112000); country.addTraffic("HighWay(KM)", 4240000); // 为了使JSON视觉上的可读性,增加一行如下代码,注意,在生产中不需要这样,因为这样会增大Json的内容 mapper.configure(SerializationFeature.INDENT_OUTPUT, true); // 配置mapper忽略空属性 mapper.setSerializationInclusion(Include.NON_EMPTY); // 默认情况,Jackson使用Java属性字段名称作为 Json的属性名称,也可以使用Jackson annotations(注解)改变Json属性名称 mapper.writeValue(new File("country.json"), country); } public static void main(String[] args) throws Exception { convert(); } }
程序运行后生成country.json,内容如下:
 
{  "country_id" : "China",  "birthDate" : "1949-10-01",  "nation" : [ "Han", "Meng", "Hui", "WeiWuEr", "Zang" ],  "lakes" : [ "Qinghai Lake", "Poyang Lake", "Dongting Lake", "Taihu Lake" ],  "provinces" : [ {    "name" : "Shanxi",    "population" : 37751200  }, {    "name" : "ZheJiang",    "population" : 55080000  } ],  "traffic" : {    "HighWay(KM)" : 4240000,    "Train(KM)" : 112000  }}
(2)Json字符串反序列化为java对象:
 
package com.jackson.json.databinding; import java.io.File;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Iterator;import java.util.List; import com.fasterxml.jackson.core.JsonParseException;import com.fasterxml.jackson.databind.DeserializationFeature;import com.fasterxml.jackson.databind.JsonMappingException;import com.fasterxml.jackson.databind.ObjectMapper; /** * 将Json字符串反序列化为Java对象 */public class JsonDeserializeToJava {        public static void main(String[] args) throws Exception {        //ObjectMapper类用序列化与反序列化映射器        ObjectMapper mapper = new ObjectMapper();        File json = new File("country.json");        //当反序列化json时,未知属性会引起的反序列化被打断,这里我们禁用未知属性打断反序列化功能,        //因为,例如json里有10个属性,而我们的bean中只定义了2个属性,其它8个属性将被忽略        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);                //从json映射到java对象,得到country对象后就可以遍历查找,下面遍历部分内容,能说明问题就可以了        Country country = mapper.readValue(json, Country.class);        System.out.println("country_id:"+country.getCountry_id());        //设置时间格式,便于阅读        SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");        String birthDate = dateformat.format(country.getBirthDate());        System.out.println("birthDate:"+birthDate);                List
provinces = country.getProvinces(); for (Province province : provinces) { System.out.println("province:"+province.name + "\n" + "population:"+province.population); } }}
程序运行结果:
 
country_id:ChinabirthDate:1949-10-01province:Shanxipopulation:37751200province:ZheJiangpopulation:55080000

2.Tree Model处理Json

(1)tree model生成json:

package com.jackson.json.treemodel; import java.io.File;import java.io.FileWriter; import com.fasterxml.jackson.core.JsonFactory;import com.fasterxml.jackson.core.JsonGenerator;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.SerializationFeature;import com.fasterxml.jackson.databind.node.ArrayNode;import com.fasterxml.jackson.databind.node.JsonNodeFactory;import com.fasterxml.jackson.databind.node.ObjectNode; public class SerializationExampleTreeModel {        public static void main(String[] args) throws Exception {        //创建一个节点工厂,为我们提供所有节点        JsonNodeFactory factory = new JsonNodeFactory(false);        //创建一个json factory来写tree modle为json        JsonFactory jsonFactory = new JsonFactory();        //创建一个json生成器        JsonGenerator generator = jsonFactory.createGenerator(new FileWriter(new File("country2.json")));        //注意,默认情况下对象映射器不会指定根节点,下面设根节点为country        ObjectMapper mapper = new ObjectMapper();        ObjectNode country = factory.objectNode();                country.put("country_id", "China");        country.put("birthDate", "1949-10-01");                //在Java中,List和Array转化为json后对应的格式符号都是"obj:[]"        ArrayNode nation = factory.arrayNode();        nation.add("Han").add("Meng").add("Hui").add("WeiWuEr").add("Zang");        country.set("nation", nation);                ArrayNode lakes = factory.arrayNode();        lakes.add("QingHai Lake").add("Poyang Lake").add("Dongting Lake").add("Taihu Lake");        country.set("lakes", lakes);                ArrayNode provinces = factory.arrayNode();        ObjectNode province = factory.objectNode();        ObjectNode province2 = factory.objectNode();        province.put("name","Shanxi");        province.put("population", 37751200);        province2.put("name","ZheJiang");        province2.put("population", 55080000);        provinces.add(province).add(province2);        country.set("provinces", provinces);                ObjectNode traffic = factory.objectNode();        traffic.put("HighWay(KM)", 4240000);        traffic.put("Train(KM)", 112000);        country.set("traffic", traffic);                mapper.configure(SerializationFeature.INDENT_OUTPUT, true);        mapper.writeTree(generator, country);    } }

程序运行生成country2.json,内容如下:

{"country_id":"China","birthDate":"1949-10-01","nation":["Han","Meng","Hui","WeiWuEr","Zang"],"lakes":["QingHai Lake","Poyang Lake","Dongting Lake","Taihu Lake"],"provinces":[{"name":"Shanxi","population":37751200},{"name":"ZheJiang","population":55080000}],"traffic":{"HighWay(KM)":4240000,"Train(KM)":112000}}

(2) json字符串反序列化为tree mode

DeserializationExampleTreeModel1.java,请注意观察程序中不同的JsonNode的类型变化

package com.jackson.json.treemodel; import java.io.File;import java.util.Iterator; import com.fasterxml.jackson.databind.JsonNode;import com.fasterxml.jackson.databind.ObjectMapper; public class DeserializationExampleTreeModel1 {     public static void main(String[] args) throws Exception {        ObjectMapper mapper = new ObjectMapper();        // Jackson提供一个树节点被称为"JsonNode",ObjectMapper提供方法来读json作为树的JsonNode根节点        JsonNode node = mapper.readTree(new File("country2.json"));        // 看看根节点的类型        System.out.println("node JsonNodeType:"+node.getNodeType());        // 是不是一个容器        System.out.println("node is container Node ? "+node.isContainerNode());        // 得到所有node节点的子节点名称        System.out.println("---------得到所有node节点的子节点名称-------------------------");        Iterator
fieldNames = node.fieldNames(); while (fieldNames.hasNext()) { String fieldName = fieldNames.next(); System.out.print(fieldName+" "); } System.out.println("\n-----------------------------------------------------"); // as.Text的作用是有值返回值,无值返回空字符串 JsonNode country_id = node.get("country_id"); System.out.println("country_id:"+country_id.asText() + " JsonNodeType:"+country_id.getNodeType()); JsonNode birthDate = node.get("birthDate"); System.out.println("birthDate:"+birthDate.asText()+" JsonNodeType:"+birthDate.getNodeType()); JsonNode nation = node.get("nation"); System.out.println("nation:"+ nation+ " JsonNodeType:"+nation.getNodeType()); JsonNode lakes = node.get("lakes"); System.out.println("lakes:"+lakes+" JsonNodeType:"+lakes.getNodeType()); JsonNode provinces = node.get("provinces"); System.out.println("provinces JsonNodeType:"+provinces.getNodeType()); boolean flag = true; for (JsonNode provinceElements : provinces) { //为了避免provinceElements多次打印,用flag控制打印,能体现provinceElements的JsonNodeType就可以了 if(flag){ System.out.println("provinceElements JsonNodeType:"+provinceElements.getNodeType()); System.out.println("provinceElements is container node? "+provinceElements.isContainerNode()); flag = false; } Iterator
provinceElementFields = provinceElements.fieldNames(); while (provinceElementFields.hasNext()) { String fieldName = (String) provinceElementFields.next(); String province; if ("population".equals(fieldName)) { province = fieldName + ":" + provinceElements.get(fieldName).asInt(); }else{ province = fieldName + ":" + provinceElements.get(fieldName).asText(); } System.out.println(province); } } }}

程序运行后打印结果如下:

node JsonNodeType:OBJECTnode is container Node ? true---------得到所有node节点的子节点名称-------------------------country_id birthDate nation lakes provinces traffic -----------------------------------------------------country_id:China JsonNodeType:STRINGbirthDate:1949-10-01 JsonNodeType:STRINGnation:["Han","Meng","Hui","WeiWuEr","Zang"] JsonNodeType:ARRAYlakes:["QingHai Lake","Poyang Lake","Dongting Lake","Taihu Lake"] JsonNodeType:ARRAYprovinces JsonNodeType:ARRAYprovinceElements JsonNodeType:OBJECTprovinceElements is container node? truename:Shanxipopulation:37751200name:ZheJiangpopulation:55080000

在来看一下DeserializationExampleTreeModel2.java,本例中使用JsonNode.path的方法,path方法类似于DeserializationExampleTreeModel1.java中使用的get方法,

但当node不存在时,get方法返回null,而path返回MISSING类型的JsonNode

package com.jackson.json.treemodel; import java.io.File;import java.io.IOException;import java.util.Iterator; import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.JsonNode;import com.fasterxml.jackson.databind.ObjectMapper; public class DeserializationExampleTreeModle2 {        public static void main(String[] args) throws JsonProcessingException, IOException{        ObjectMapper mapper = new ObjectMapper();        JsonNode node = mapper.readTree(new File("country2.json"));        //path方法获取JsonNode时,当对象不存在时,返回MISSING类型的JsonNode        JsonNode missingNode = node.path("test");        if(missingNode.isMissingNode()){            System.out.println("JsonNodeType : " + missingNode.getNodeType());        }         System.out.println("country_id:"+node.path("country_id").asText());                JsonNode provinces = node.path("provinces");        for (JsonNode provinceElements : provinces) {            Iterator
provincesFields = provinceElements.fieldNames(); while (provincesFields.hasNext()) { String fieldName = (String) provincesFields.next(); String province; if("name".equals(fieldName)){ province = fieldName +":"+ provinceElements.path(fieldName).asText(); }else{ province = fieldName +":"+ provinceElements.path(fieldName).asInt(); } System.out.println(province); } } } }

程序运行打印结果:

JsonNodeType : MISSINGcountry_id:Chinaname:Shanxipopulation:37751200name:ZheJiangpopulation:55080000

3.Stream处理Json

(1)stream生成json

 

package com.jackson.json.streaming; import java.io.File;import java.io.FileWriter;import java.io.Exception; import com.fasterxml.jackson.core.JsonFactory;import com.fasterxml.jackson.core.JsonGenerator; public class StreamGeneratorJson {        public static void main(String[] args) throws Exception {        JsonFactory factory = new JsonFactory();        //从JsonFactory创建一个JsonGenerator生成器的实例        JsonGenerator generator = factory.createGenerator(new FileWriter(new File("country3.json")));                generator.writeStartObject();        generator.writeFieldName("country_id");        generator.writeString("China");        generator.writeFieldName("provinces");        generator.writeStartArray();        generator.writeStartObject();        generator.writeStringField("name", "Shanxi");        generator.writeNumberField("population", 33750000);        generator.writeEndObject();        generator.writeEndArray();        generator.writeEndObject();                generator.close();    } }
程序运行后生成country3.json文件内容:
 
{"country_id":"China","provinces":[{"name":"Shanxi","population":33750000}]}

(2)stream解析json:

现在adgcountry3.json,我们用Streaming API的方式来解析上面的Json,并查找json中population的值。

package com.jackson.json.streaming; import java.io.File;import java.io.IOException; import com.fasterxml.jackson.core.JsonFactory;import com.fasterxml.jackson.core.JsonParseException;import com.fasterxml.jackson.core.JsonParser;import com.fasterxml.jackson.core.JsonToken; /*Jackson API提供了token对每个Json对象,例如,Json开始符号“{”是token指向的第一个解析的对象, key:value键值对是另一个单独的对象。这个API很强大,但也需要编写大量代码。不推荐使用,平时更多的是使用DataBinding和TreeModel来处理json */public class StreamParserJson {    public static void main(String[] args) throws JsonParseException,            IOException {        JsonFactory factory = new JsonFactory();        // 从JsonFactory创建JsonParser解析器的实例        JsonParser parser = factory.createParser(new File("country3.json"));         while (!parser.isClosed()) {            // 得到一个token,第一次遍历时,token指向json文件中第一个符号"{"            JsonToken token = parser.nextToken();            if (token == null) {                break;            }            // 我们只查找 country3.json中的"population"字段的值,能体现解析的流程就可以了            // 当key是provinces时,我们进入provinces,查找population            if (JsonToken.FIELD_NAME.equals(token)                    && "provinces".equals(parser.getCurrentName())) {                token = parser.nextToken();                if (!JsonToken.START_ARRAY.equals(token)) {                    break;                }                // 此时,token指向的应该是"{"                token = parser.nextToken();                if (!JsonToken.START_OBJECT.equals(token)) {                    break;                }                while (true) {                    token = parser.nextToken();                    if (token == null) {                        break;                    }                    if (JsonToken.FIELD_NAME.equals(token)                            && "population".equals(parser.getCurrentName())) {                        token = parser.nextToken();                        System.out.println(parser.getCurrentName() + " : "                                + parser.getIntValue());                    }                }            }        }    } }
程序运行后,在控制台打印结果如下:
 
population : 33750000

总结

上面的例子中,分别用3种方式处理Json,我的体会大致如下:
 
Stream API方式是开销最低、效率最高,但编写代码复杂度也最高,在生成Json时,需要逐步编写符号和字段拼接json,在解析Json时,需要根据token指向也查找json值,生成和解析json都不是很方便,代码可读性也很低。
Databinding处理Json是最常用的json处理方式,生成json时,创建相关的java对象,并根据json内容结构把java对象组装起来,最后调用writeValue方法即可生成json,
解析时,就更简单了,直接把json映射到相关的java对象,然后就可以遍历java对象来获取值了。
TreeModel处理Json,是以树型结构来生成和解析json,生成json时,根据json内容结构,我们创建不同类型的节点对象,组装这些节点生成json。解析json时,它不需要绑定json到java bean,根据json结构,使用path或get方法轻松查找内容。
 
学习参考:
转:
 
 

转载于:https://www.cnblogs.com/wynjauu/articles/9467000.html

你可能感兴趣的文章
linux下编译复数类型引发的错误:expected unqualified-id before '(' token
查看>>
codeforces 1041A Heist
查看>>
字典常用方法
查看>>
Spring Cloud Stream消费失败后的处理策略(三):使用DLQ队列(RabbitMQ)
查看>>
python的猴子补丁monkey patch
查看>>
架构模式: API网关
查看>>
正则验证积累
查看>>
Linux学习-汇总
查看>>
83. 删除排序链表中的重复元素
查看>>
bzoj1048 [HAOI2007]分割矩阵
查看>>
python中的__init__ 、__new__、__call__等内置函数的剖析
查看>>
Java中的编码
查看>>
PKUWC2018 5/6
查看>>
As-If-Serial 理解
查看>>
雷林鹏分享:Redis 简介
查看>>
洛谷P1005 矩阵取数游戏
查看>>
在Silverlight中使用HierarchicalDataTemplate为TreeView实现递归树状结构
查看>>
无线通信基础(一):无线网络演进
查看>>
如何在工作中快速成长?阿里资深架构师给工程师的10个简单技巧
查看>>
WebSocket 时时双向数据,前后端(聊天室)
查看>>