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開頭html
Jackson Home Page:https://github.com/FasterXML/jackson
Jackson Wiki:http://wiki.fasterxml.com/JacksonHome
Jackson doc: https://github.com/FasterXML/jackson-docs
Jackson Download Page:http://wiki.fasterxml.com/JacksonDownloadjava
本文全部程序都基於JDK1.7,依賴jackon的三個核心類庫:
jackson-core-2.5.3.jar
jackson-annotations-2.5.3.jar
jackson-databind-2.5.3.jarnode
Jackson提供了三種可選的Json處理方法:流式API(Streaming API) 、樹模型(Tree Model)、數據綁定(Data Binding)。從使用角度來看,比較一下這三種處理Json的方式的特性:git
Streaming API:是效率最高的處理方式(開銷低、讀寫速度快,但程序編寫複雜度高)下面咱們經過例子程序分別使用DataBinding,TreeModel,Streaming的方式來建立和解析Json字符串github
package com.jackson.json.databinding; public class Province { public String name; public int population; public String[] city; }
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<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 + "]"; } }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<String> nation = new ArrayList<String>(); 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<Province> provinces = new ArrayList<Province>(); 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_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 } }
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<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)tree model生成json:web
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,內容以下:json
(2) json字符串反序列化爲tree modemarkdown
DeserializationExampleTreeModel1.java,請注意觀察程序中不一樣的JsonNode的類型變化app
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<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
在來看一下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<String> 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 : MISSING country_id:China name:Shanxi population:37751200 name:ZheJiang population:55080000
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文件內容:
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()); } } } } } }