基本介绍
Jackson框架是基于Java平台的一套数据处理工具,被称为\\”最好的Java Json解析器\\”,目前Jackson主要有1.x和2.x两个分支版本,其中1.x的类库中包命名以org.codehaus.jackson.xxx开头,2.x类库中包命令com.fastxml.jackson.xxx开头,Jackson框架包含以下3个核心库:
-
streaming
-
databind
-
annotations.Jackson
解析处理
ObjectMapper是Jackson库的主要类,它可以将JSON数据转换成Java对象或者将JAVA对象序列化为JSON数据,ObjectMapper通过JsonParser和JsonGenerator的实例实现JSON实际的读/写
类声明
org.codehaus.jackson.map.ObjectMapper类的声明如下:
public class ObjectMapperextends ObjectCodecimplements Versioned
嵌套类
-
static class ObjectMapper.DefaultTypeResolverBuilder:定制TypeResolverBuilder,提供所谓的\\”默认输入\\”使用类型解析构建器
构造函数
-
ObjectMapper():默认的构造函数,使用StdSerializerProvider作为其SerializerProvider,并使用BeanSerializerFactory作为其SerializerFactory
-
ObjectMapper(JsonFactory jf):使用指定的JsonFactory构建必要的JsonParsers和/或JsonGenerators映射
-
ObjectMapper(JsonFactory jf, SerializerProvider sp, DeserializerProvider dp)
-
ObjectMapper(JsonFactory jf, SerializerProvider sp, DeserializerProvider dp, SerializationConfig sconfig, DeserializationConfig dconfig)
-
ObjectMapper(SerializerFactory sf):可以设置序列化工厂setSerializerFactory(org.codehaus.jackson.map.SerializerFactory)
继承的方法
ObjectMapper类继承了java.lang.Objec类方法
数据处理
Json处理方法分类
Jackson支持Java对象与Json之间的相互转化,Java对象序列化为Json字符串,Json字符串也可以反序列化为相同的Java对象,Jackson提供了三种可选的Json处理方法:
-
树模型(Tree Model):是最灵活的处理方式
-
流式API(Streaming API):是效率最高的处理方式(开销低、读写速度快,但程序编写复杂度高)
-
数据绑定(Data Binding):是最常用的处理方式
下面从结合具体的实战来看一下,首先在pom.xml文件中添加以下三个依赖:
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.10</version></dependency><!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.9.10</version></dependency><!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.9.10</version></dependency>
树模型(Tree Model)
tree model生成json
package com.jacksonTest;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;import java.io.File;import java.io.FileWriter;public class SerializationExampleTreeModel {public static void main(String[] args) throws Exception {//创建一个节点工厂,为我们提供所有节点JsonNodeFactory factory = new JsonNodeFactory(false);//创建一个json factory来写tree modle为jsonJsonFactory jsonFactory = new JsonFactory();//创建一个json生成器JsonGenerator generator = jsonFactory.createGenerator(new FileWriter(new File(\\\"country2.json\\\")));//注意,默认情况下对象映射器不会指定根节点,下面设根节点为countryObjectMapper 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}}
json反序列化为tree mode1
package com.jacksonTest;import com.fasterxml.jackson.databind.JsonNode;import com.fasterxml.jackson.databind.ObjectMapper;import java.io.File;import java.util.Iterator;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);}}}}
程序运行后打印结果如下:

json反序列化为tree mode2
再来看一下DeserializationExampleTreeModel2.java,本例中使用JsonNode.path的方法,path方法类似于DeserializationExampleTreeModel1.java中使用的get方法, 但当node不存在时get方法返回null,而path返回MISSING类型的JsonNode
package com.jacksonTest;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.JsonNode;import com.fasterxml.jackson.databind.ObjectMapper;import java.io.File;import java.io.IOException;import java.util.Iterator;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类型的JsonNodeJsonNode 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);}}}}
程序运行打印结果:

流式API(Streaming API)
Stream生成json
package com.jacksonTest;import com.fasterxml.jackson.core.JsonFactory;import com.fasterxml.jackson.core.JsonGenerator;import java.io.File;import java.io.FileWriter;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文件内容:

stream解析json
现在我们用Streaming API的方式来解析上面的Json,并查找json中population的值:
package com.jacksonTest;import com.fasterxml.jackson.core.JsonFactory;import com.fasterxml.jackson.core.JsonParseException;import com.fasterxml.jackson.core.JsonParser;import com.fasterxml.jackson.core.JsonToken;import java.io.File;import java.io.IOException;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,查找populationif (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());}}}}}}
程序运行后,在控制台打印结果如下:

数据绑定(Data Binding)
数据绑定简介
数据绑定API用于JSON转换和使用属性访问或使用注解POJO(普通Java对象),以下是它的两个类型:
-
简单数据绑定 – 转换JSON,从Java Maps, Lists, Strings, Numbers, Booleans和null对象
-
完整数据绑定 – 转换JSON到任何JAVA类型
ObjectMapper读/写JSON两种类型的数据绑定,数据绑定是最方便的方式是类似XML的JAXB解析器
简单数据绑定
简单的数据绑定是指JSON映射到Java核心数据类型,下表列出了JSON类型和Java类型之间的关系:

具体代码示例:
package com.jacksonTest;import com.fasterxml.jackson.core.JsonParseException;import com.fasterxml.jackson.databind.JsonMappingException;import com.fasterxml.jackson.databind.ObjectMapper;import java.io.File;import java.io.IOException;import java.util.HashMap;import java.util.Map;public class JacksonTester {public static void main(String args[]){JacksonTester tester = new JacksonTester();try {ObjectMapper mapper = new ObjectMapper();Map<String,Object> studentDataMap = new HashMap<String,Object>();int[] marks = {1,2,3};Student student = new Student();student.setAge(10);student.setName(\\\"Mahesh\\\");// JAVA ObjectstudentDataMap.put(\\\"student\\\", student);// JAVA StringstudentDataMap.put(\\\"name\\\", \\\"Mahesh Kumar\\\");// JAVA BooleanstudentDataMap.put(\\\"verified\\\", Boolean.FALSE);// ArraystudentDataMap.put(\\\"marks\\\", marks);mapper.writeValue(new File(\\\"student.json\\\"), studentDataMap);//result student.json//{// \\\"student\\\":{\\\"name\\\":\\\"Mahesh\\\",\\\"age\\\":10},// \\\"marks\\\":[1,2,3],// \\\"verified\\\":false,// \\\"name\\\":\\\"Mahesh Kumar\\\"//}studentDataMap = mapper.readValue(new File(\\\"student.json\\\"), Map.class);System.out.println(studentDataMap.get(\\\"student\\\"));System.out.println(studentDataMap.get(\\\"name\\\"));System.out.println(studentDataMap.get(\\\"verified\\\"));System.out.println(studentDataMap.get(\\\"marks\\\"));} catch (JsonParseException e) {e.printStackTrace();} catch (JsonMappingException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}class Student {private String name;private int age;public Student(){}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String toString(){return \\\"Student [ name: \\\"+name+\\\", age: \\\"+ age+ \\\" ]\\\";}}
运行结果如下所示:

完全数据绑定
完全数据绑定是指JSON映射到任何Java对象,例如:
//Create an ObjectMapper instanceObjectMapper mapper = new ObjectMapper();//map JSON content to Student objectStudent student = mapper.readValue(new File(\\\"student.json\\\"), Student.class);//map Student object to JSON contentmapper.writeValue(new File(\\\"student.json\\\"), student);
具体代码示例:
package com.jacksonTest;import com.fasterxml.jackson.core.JsonGenerationException;import com.fasterxml.jackson.core.JsonParseException;import com.fasterxml.jackson.databind.JsonMappingException;import com.fasterxml.jackson.databind.ObjectMapper;import java.io.File;import java.io.IOException;public class JacksonTester {public static void main(String args[]){JacksonTester tester = new JacksonTester();try {Student student = new Student();student.setAge(10);student.setName(\\\"Mahesh\\\");tester.writeJSON(student);Student student1 = tester.readJSON();System.out.println(student1);} catch (JsonParseException e) {e.printStackTrace();} catch (JsonMappingException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}private void writeJSON(Student student) throws JsonGenerationException, JsonMappingException, IOException{ObjectMapper mapper = new ObjectMapper();mapper.writeValue(new File(\\\"student.json\\\"), student);}private Student readJSON() throws JsonParseException, JsonMappingException, IOException{ObjectMapper mapper = new ObjectMapper();Student student = mapper.readValue(new File(\\\"student.json\\\"), Student.class);return student;}}class Student {private String name;private int age;public Student(){}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String toString(){return \\\"Student [ name: \\\"+name+\\\", age: \\\"+ age+ \\\" ]\\\";}}
运行结果如下所示:

java对象序列化为json
Province.java:
package com.jacksonTest;public class Province {public String name;public int population;public String[] city;}
Country.java:
package com.jacksonTest;import java.util.*;public class Country {// 注意:被序列化的bean的private属性字段需要创建getter方法或者属性字段应该为publicprivate 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;}@Overridepublic String toString() {return \\\"Country [country_id=\\\" + country_id + \\\", birthDate=\\\" + birthDate+ \\\", nation=\\\" + nation + \\\", lakes=\\\" + Arrays.toString(lakes)+ \\\", province=\\\" + provinces + \\\", traffic=\\\" + traffic + \\\"]\\\";}}
JavaBeanSerializeToJson.java
package com.jacksonTest;import com.fasterxml.jackson.annotation.JsonInclude;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.SerializationFeature;import java.io.File;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.List;public class JavaBeanSerializeToJson {public static void convert() throws Exception {// 使用ObjectMapper来转化对象为JsonObjectMapper 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(JsonInclude.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:
Json反序列化为java对象
package com.jacksonTest;import com.fasterxml.jackson.databind.DeserializationFeature;import com.fasterxml.jackson.databind.ObjectMapper;import java.io.File;import java.text.SimpleDateFormat;import java.util.List;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);}}}
程序运行结果:
ObjectMapper使用特性
在默认情况下ObjectMapper在序列化时会将所有的字段逐一序列化,无论这些字段是否有值,或者为null,另外序列化依赖于getter方法,如果某个字段没有getter方法,那么该字段是不会被序列化的,由此可见在序列化时OjbectMapper是通过反射机制找到了对应的getter,然后将getter方法对应的字段序列化到Json中~
原创文章,作者:七芒星实验室,如若转载,请注明出处:https://www.sudun.com/ask/34164.html