Java中Jackson包解析Json格式总结
Jackson框架是基于Java平台的一套数据处理工具,它包含了3个核心库:streaming,databind,annotations,被称为“最好的Java Json解析器”。
下载
Jackson的jar包下载地址:http://jackson.codehaus.org/1.7.6/jackson-all-1.7.6.jar
下载完毕导入jar包,依赖jackon的三个核心类库:
jackson-core-2.5.3.jar 定义了底层的streaming API和实现了Json特性。
jackson-annotations-2.5.3.jar 包含了标准的Jackson注解。
jackson-databind-2.5.3.jar 实现了数据绑定和对象序列化,它依赖于streaming和annotations的包。
解析Json的3种方式
流式API(Streaming API)
Jackson API提供了token对每个Json对象,例如,Json开始符号“{”是token指向的第一个解析的对象,key:value键值对是另一个单独的对象。这个API很强大,但也需要编写大量代码。不推荐使用,平时更多的是使用DataBinding和TreeModel来处理json。
//测试json1 { "country_id": "China", "provinces": [{ "name": "Shanxi", "population": 33750000 }] }
//查找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; public class StreamParserJson { public static void main(String[] args) throws JsonParseException, IOException { JsonFactory factory = new JsonFactory(); // 从JsonFactory创建JsonParser解析器的实例 JsonParser parser = factory.createParser(new File("测试json1.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
树模型(Tree Model)
Tree Model是最灵活的处理json的方式
//测试json2 { "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 } }
//解析json字符串进行反序列化 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 < String > 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 < String > 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:OBJECT node is container Node ? true ---------得到所有node节点的子节点名称------------------------- country_id birthDate nation lakes provinces traffic ----------------------------------------------------- country_id:China JsonNodeType:STRING birthDate:1949-10-01 JsonNodeType:STRING nation:["Han","Meng","Hui","WeiWuEr","Zang"] JsonNodeType:ARRAY lakes:["QingHai Lake","Poyang Lake","Dongting Lake","Taihu Lake"] JsonNodeType:ARRAY provinces JsonNodeType:ARRAY provinceElements JsonNodeType:OBJECT provinceElements is container node? true name:Shanxi population:37751200 name:ZheJiang population:55080000
数据绑定(Data Binding)
Data Binding是最常用的解析json方式
//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 } }
//Province.java public class Province { public String name; public int population; public String[] city; }
//Country.java public class Country { // 注意:被序列化的bean的private属性字段需要创建getter方法或者属性字段应该为public private String country_id; private Date birthDate; private List<String> nation = new ArrayList<String>(); private String[] lakes; private List<Province> provinces = new ArrayList<Province>(); private Map<String, Integer> traffic = new HashMap<String, Integer>(); 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<String> getNation() { return nation; } public void setNation(List<String> 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<String, Integer> getTraffic() { return traffic; } public void setTraffic(Map<String, Integer> traffic) { this.traffic = traffic; } public void addTraffic(String key, Integer value) { traffic.put(key, value); } public List<Province> getProvinces() { return provinces; } public void setProvinces(List<Province> 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 + "]"; } }
/**
* 解析Json字符串反序列化为Java对象
*/
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 < Province > provinces = country.getProvinces();
for (Province province: provinces) {
System.out.println("province:" + province.name + "\n" + "population:" + province.population);
}
}
运行结果:
country_id:China birthDate:1949-10-01 province:Shanxi population:37751200 province:ZheJiang population:55080000
总结
1. Stream API方式是开销最低、效率最高,但编写代码复杂度也最高,在生成Json时,需要逐步编写符号和字段拼接json,在解析Json时,需要根据token指向也查找json值,生成和解析json都不是很方便,代码可读性也很低。
2. Databinding处理Json是最常用的json处理方式,生成json时,创建相关的java对象,并根据json内容结构把java对象组装起来,最后调用writeValue方法即可生成json,解析时,就更简单了,直接把json映射到相关的java对象,然后就可以遍历java对象来获取值了。
3. TreeModel处理Json,是以树型结构来生成和解析json,生成json时,根据json内容结构,我们创建不同类型的节点对象,组装这些节点生成json。解析json时,它不需要绑定json到java bean,根据json结构,使用path或get方法轻松查找内容。
版权声明:本文为JAVASCHOOL原创文章,未经本站允许不得转载。