Jackson详细介绍
Jackson 是一个能够将java对象序列化为JSON字符串,也能够将JSON字符串反序列化为java对象的框架。
本文的所有内容都可以从 Java JSON Jackson Introduction 中找到,这里记录下来供自己以后参考,如果时间充足,建议阅读原文。
这是另一篇介绍自定义(反)序列化的文章 http://www.baeldung.com/jackson-custom-serialization
无论是序列化还是反序列化,Jackson都提供了三种方式:
1. JSON <--> Java Object
2. JSON <--> JsonNode Tree(类似于XML的DOM树)
3. JSON <--> Json Stream (这是一个低层次的api,很强大,但是很繁琐)
Jackson提供了很多有用的注解来定制序列化,但是我们完全不用它的注解也可以完成绝大多数的工作。下面就从上面三种方式来一一介绍。
JSON <--> Java Object
下面的Person类是一个普通的java POJO。它含有基本类型(包括String、Date)和一些集合类型,以及一个自定义的Address类型。
注意: 默认情况下,Jackson会处理所有public的属性和拥有getter方法的属性(反序列化需要setter)
![](/assets/blank.gif)
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 Person {private String name;private int age;public Date birth;private Address address;private List<String> friends = new ArrayList<>();public Map<String, String> info = new HashMap<>();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 List<String> getFriends() {return friends;}public void setFriends(List<String> friends) {this.friends = friends;}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}//注意这个默认构造器,如果没有默认的构造器,应该有一个@JsonCreator修饰的构造器public Person(){}public Person(String name, int age, Address address, Date birth, String... friends){this.name = name;this.age = age;this.address = address;this.birth = birth;this.friends.addAll(Arrays.asList(friends));}@Overridepublic String toString() {StringBuffer sb = new StringBuffer();sb.append("name: " + this.name + "\n");sb.append("age: " + this.age + "\n");sb.append("address: " + this.address + "\n");sb.append("birth: " + this.birth + "\n");this.friends.forEach(x -> sb.append("friend:"+ x + "\n"));return sb.toString();} }
![](/assets/blank.gif)
![](/assets/blank.gif)
public class Address {public String homeAddress;public String workAddress;//跟Person一样,我们也必须提供一个无参的默认构造器public Address(){}public Address(String homeAddress, String workAddress) {this.homeAddress = homeAddress;this.workAddress = workAddress;}@Overridepublic String toString() {return "home:" + this.homeAddress + " " + "work:" + this.workAddress;} }
![](/assets/blank.gif)
下面我们使用Jackson来(反)序列化 这个Person对象。
序列化:
![](/assets/blank.gif)
import java.io.File; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date;import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature;public class SerializeTest {public static void main(String[] args) throws ParseException, JsonGenerationException, JsonMappingException, IOException {SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");Date birth = format.parse("2010-10-10");Address address = new Address("New York", "Tokyo");Person person = new Person("zhangsan", 11, address, birth, "weiying", "caifang");person.info.put("height", "175cm");person.info.put("weight", "80kg");//使用ObjectMapper来序列化和反序列化ObjectMapper mapper = new ObjectMapper();//配置序列化的输出缩进mapper.configure(SerializationFeature.INDENT_OUTPUT, true);//如果没有DateFormat,ObjectMapper将会把Date类型序列化为毫秒数 mapper.setDateFormat(format);//按照map的key的自然排序来产生序列化结果mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);//序列化的过程就这一行代码,当然也可以选择输出到文件或其他流中mapper.writeValue(new File("person.json"), person);} }
![](/assets/blank.gif)
反序列化:
![](/assets/blank.gif)
import java.io.File; import java.io.IOException;import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper;public class DeserializeTest {public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {//反序列化同样从ObjectMapper开始ObjectMapper mapper = new ObjectMapper();//配置在反序列化过程中如果json字符串中存在无法匹配的属性不会失败mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);//上面的configure(xxx,false) 等同于disable(xxx),例如下面这行和上面作用是一样的。 mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);//反序列化的过程也仅仅只有一行代码,同样可以从文件或其他流等输入中进行反序列化Person person = mapper.readValue(new File("person.json"), Person.class);System.out.println(person);} }
![](/assets/blank.gif)
在上面的例子中我们看到了Jackson最基本的(反)序列化过程,下面我们介绍一些用来定制(反)序列化的注解:
1.@JsonProperty - 在默认情况下,Jackson会处理所有public的属性和拥有getter(序列化)和setter(反序列化)的属性。但是我们可以使用 @JsonProperty来手动指定我们希望jackson处理的属性。于此同时,我们可以改变java对象映射到json中的属性名称(默认是相同的)。@JsonProperty相当于JAXB中的@XmlElement注解。
![](/assets/blank.gif)
import java.io.File; import java.io.IOException;import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature;/*** 这个Dog类型没有任何public的属性和getter方法,但是我们使用@JsonProperty可以手动指定希望(反)序列化的属性,并能指定希望映射到json中的属性名称*/ public class Dog {@JsonProperty("dog_name")private String name = "dahuang";private int age;@JsonProperty("dog_age")private int tellYourAge(){return this.age;}@JsonProperty("dog_age")private void giveMeAge(int age){this.age = age;}@Overridepublic String toString() {return "dog(name: " + name + ";age: " + age + ")";}public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException {ObjectMapper mapper = new ObjectMapper();//Jackson序列化空对象默认为失败 mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);//配置ObjectMapper有两种方式,除了上面那种,下面这行代码是等价的。mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);//配置序列化格式 mapper.enable(SerializationFeature.INDENT_OUTPUT);//上面这行代码同样等价于下面这行mapper.configure(SerializationFeature.INDENT_OUTPUT, true);mapper.writeValue(new File("dog.json"), new Dog());Dog dog = mapper.readValue(new File("dog.json"), Dog.class);System.out.println(dog);} }
![](/assets/blank.gif)
2.@JsonCreator - 在上面Person的例子中,我们除了定义了一个有参数的构造器外,还必须定义一个无参的默认构造器,这是因为在反序列化的过程中,Jackson不知道该向那个有参数的构造器中传递什么参数。 我们可以在构造器上使用 @JsonCreator,并在参数列表中使用@JsonProperty,这样在反序列化时Jackson就知道该如何使用这个构造器了,这个时候我们也就没必要定义那个无参的默认构造器了。
注意@JsonCreator仅仅在反序列化的过程中有用。
![](/assets/blank.gif)
import java.io.File; import java.io.IOException;import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper;public class Dog {public String name;public int age;@Overridepublic String toString() {return this.name + ":" + this.age;}//在反序列化的过程中,Jackson会将json串中的name属性传递给dog_name参数, 把json串中的age属性传递给dog_age参数。 @JsonCreatorpublic Dog(@JsonProperty("name") String dog_name, @JsonProperty("age") int dog_age){this.name = dog_name;this.age = dog_age;}public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException {ObjectMapper mapper = new ObjectMapper();mapper.writeValue(new File("dog.json"), new Dog("dahuang", 11));Dog dog = mapper.readValue(new File("dog.json"), Dog.class);System.out.println(dog);} }
![](/assets/blank.gif)
3.@JsonAnyGetter and @JsonAnySetter - 设想这样一种场景:除了java对象中明确指定的属性(包括使用@JsonProperty修饰指定的)外,我们希望能够随机的增加一些其他属性,让这些随机的属性也可以映射到json中去。这个时候我们就可以将这些不确定的属性放到一个map中去,并使用@JsonAnyGetter和@JsonAnySetter来修饰处理这个map的方法,然后Jackson就可以处理这些不确定的属性了。这两个属性相当于JAXB中的@XmlAnyElement和@XMLAnyAttribute。
![](/assets/blank.gif)
import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map;import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper;public class Dog {private Map<String, String> any = new HashMap<>();@JsonAnyGetterpublic Map<String, String> getAny(){return this.any;}@JsonAnySetterpublic void setAny(String key, String value){this.any.put(key, value);}public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException {Dog dog = new Dog();//suck a big dog!!!dog.setAny("height", "175cm");dog.setAny("weight", "80kg");ObjectMapper mapper = new ObjectMapper();mapper.writerWithDefaultPrettyPrinter().writeValue(new File("dog.json"), dog);Dog dog2 = mapper.readValue(new File("dog.json"), Dog.class);dog2.getAny().forEach((x, y) -> System.out.println(x + "-->" + y));} }
![](/assets/blank.gif)
4.@JsonIgnoreProperties and @JsonIgnore - 如果我们不希望Jackson处理java对象中public的属性或者拥有getter方法的属性,我们就可以使用这两个属性来忽略它们,相当于JAXB中@XmlTransient。
![](/assets/blank.gif)
import java.io.IOException;import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature;@JsonIgnoreProperties({"name", "age"}) public class Dog {public String name = "dahuang";public int age = 11;@JsonIgnorepublic String home = "CHN";public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException {ObjectMapper mapper = new ObjectMapper();mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);//Dog的所有属性都已经被忽略了,所以此时应该序列化为一个空json串mapper.writeValue(System.out, new Dog());}}
![](/assets/blank.gif)
除了使用@JsonIgnoreProperties and @JsonIgnore来忽略特定属性外,还可以像下面这样忽略空的属性:
![](/assets/blank.gif)
import java.io.IOException; import java.util.ArrayList; import java.util.List;import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature;public class Dog {public String name = "";public List<String> info = new ArrayList<>();public List<String> info2 = null;public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException {ObjectMapper mapper = new ObjectMapper();mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);//下面这行代码会忽略所有null或者空的属性,所以Dog此时依旧会被序列化为空JSON串 mapper.setSerializationInclusion(Include.NON_EMPTY);mapper.writeValue(System.out, new Dog());} }
![](/assets/blank.gif)
5.在序列化的过程中保存类型信息
下面定义了一个父类Animal和它的两个子类Dog和Cat,Person类有一个Animal类型的属性。
Animal:
![](/assets/blank.gif)
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty;public class Animal {public String name;public int age;@JsonCreatorpublic Animal(@JsonProperty("name") String name, @JsonProperty("age") int age){this.name = name;this.age = age;} }
![](/assets/blank.gif)
Dog:
![](/assets/blank.gif)
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty;public class Dog extends Animal{public String size;@JsonCreatorpublic Dog(@JsonProperty("name") String name, @JsonProperty("age") int age, @JsonProperty("size") String size){super(name, age);this.size = size;} }
![](/assets/blank.gif)
Cat:
![](/assets/blank.gif)
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty;public class Cat extends Animal{public String color;@JsonCreatorpublic Cat(@JsonProperty("name") String name, @JsonProperty("age") int age, @JsonProperty("color") String color){super(name, age);this.color = color;} }
![](/assets/blank.gif)
Person:
public class Person {public Animal animal; }
我们现在为Person的animal属性设置为Dog对象,然后序列化Person对象,之后再用得到的json串反序列化。
![](/assets/blank.gif)
import java.io.File; import java.io.IOException;import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper;public class Test {public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException {Person person = new Person();person.animal = new Dog("dahuang", 11, "big");ObjectMapper mapper = new ObjectMapper();mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);mapper.writeValue(new File("person.json"), person);Person p2 = mapper.readValue(new File("person.json"), Person.class);//在序列化的时候我们为Person对象animal属性赋予的是一个Dog对象,但是反序列化后得到的animal属性仅仅是一个animal对象。//实际上,如果Animal是一个抽象类型的话,此时就会报错了。 System.out.println(p2.animal.getClass().getName());} }
![](/assets/blank.gif)
在上面的例子序列化的结果是:
![](/assets/blank.gif)
{"animal" : {"name" : "dahuang","age" : 11,"size" : "big"} }
![](/assets/blank.gif)
在上面的结果中我们看到Jackson并没有将animal属性的具体类型信息保存下来,这样在反序列化的时候,Jackson就无法知道之前序列化时的真正类型,这就是上面反序列化后得到的是一个Animal而不是Dog的原因。
我们修改Animal如下:
![](/assets/blank.gif)
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo.As;@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = As.PROPERTY, property = "@class") @JsonSubTypes({ @Type(value = Dog.class, name = "lion"), @Type(value = Cat.class, name = "elephant") }) public class Animal {public String name;public int age;@JsonCreatorpublic Animal(@JsonProperty("name") String name, @JsonProperty("age") int age){this.name = name;this.age = age;} }
![](/assets/blank.gif)
然后再次执行上面那段序列化和反序列化的代码,便可以得到Person的animal属性是一个Dog对象了。 序列化的json为:
![](/assets/blank.gif)
{"animal" : {"@class" : "com.massclouds.info.Dog","name" : "dahuang","age" : 11,"size" : "big"} }
![](/assets/blank.gif)
我们看到上面的json结果中多了一个@class的属性,它就代表了animal属性的类型信息。
当我们直接序列化一个Animal的list或者以Animal为value的map时,上面的设置依旧无法将类型信息保存到json串中,下面我们演示如何直接(反)序列化包含Animal的list和map(注意此时Animal上的注解依旧要有)。
序列化:
![](/assets/blank.gif)
import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature;public class SerializeList {public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException {List<Animal> animal_list = new ArrayList<>();animal_list.add(new Dog("dahuang", 11, "big"));animal_list.add(new Cat("miaomiao", 11, "grey"));Map<String, Animal> animal_map = new HashMap<>();animal_map.put("dog", new Dog("dahuagn", 11, "big"));animal_map.put("cat", new Cat("miaomiao", 11, "white"));ObjectMapper mapper = new ObjectMapper();mapper.enable(SerializationFeature.INDENT_OUTPUT);mapper.writerFor(new TypeReference<List<Animal>>(){}).writeValue(new File("list.json"), animal_list);mapper.writerFor(new TypeReference<Map<String, Animal>>(){}).writeValue(new File("map.json"), animal_map);} }
![](/assets/blank.gif)
反序列化:
![](/assets/blank.gif)
import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map;import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper;public class SerializeList {public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException {ObjectMapper mapper = new ObjectMapper();List<Animal> animal_list = mapper.readValue(new File("list.json"), new TypeReference<List<Animal>>(){});animal_list.forEach(animal -> System.out.println(animal.getClass().getName()));Map<String, Animal> animal_map = mapper.readValue(new File("map.json"), new TypeReference<Map<String, Animal>>(){});animal_map.forEach((key, value) -> System.out.println(key + " --> " + value.getClass().getName()));} }
![](/assets/blank.gif)
上面需要注意的地方就是 由于Class对象中是不能携带泛型信息的,所以需要使用TypeReference。
6. Mix-in
当我们使用的是第三方类库中的Java类型时,我们无法直接在类型上使用注解,此时我们可以使用Jackson提供的Mix-in功能。
我们有一个Dog类如下:
![](/assets/blank.gif)
public class Dog {public String name;private int age;public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Dog(String name, int age){this.name = name;this.age = age;} }
![](/assets/blank.gif)
我们需要定义一个抽象类,如果我们希望在Dog类的什么地方使用注解,我们就在这个抽象类中定义一个相同的声明(属性或者方法),然后使用注解,例如我们希望在Dog中的getAge方法上使用@JsonProperty注解,那么我们就在这个抽象类中定义一个名称为getAge的抽象方法,然后再在这个抽象方法上使用@JsonProperty。下面是这个抽象类的实现:
![](/assets/blank.gif)
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty;public abstract class DogMixin{@JsonProperty("dog_name")public String name;@JsonProperty("dog_age")public abstract int getAge();@JsonProperty("dog_age")public abstract void setAge(int age);@JsonCreatorpublic DogMixin(@JsonProperty("dog_name") String name,@JsonProperty("dog_age") int age){//这里可以啥都没有。。。 } }
![](/assets/blank.gif)
然后在序列化的时候,像下面这样使用,就可以跟直接在Dog类中使用注解产生一样的效果了。
![](/assets/blank.gif)
import java.io.File; import java.io.IOException;import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper;public class Test {public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException {ObjectMapper mapper = new ObjectMapper();//注册我们使用的Mixin抽象类mapper.addMixIn(Dog.class, DogMixin.class);Dog dog = new Dog("dahuang", 11);mapper.writerWithDefaultPrettyPrinter().writeValue(new File("dog.json"), dog);Dog dog2 = mapper.readValue(new File("dog.json"), Dog.class);System.out.println(dog2.getAge() + " : " + dog2.name);} }
![](/assets/blank.gif)
JSON <--> JsonNode Tree
就如同XML的DOM树一样,我们同样可以通过一颗json节点树来构建json,当然也可以将一个json字符串反序列化为一颗节点树。
Tree2JSON
![](/assets/blank.gif)
import java.io.FileOutputStream; import java.io.IOException;import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode;public class Tree2JSON {public static void main(String[] args) throws IOException {JsonFactory jsonFactory = new JsonFactory();JsonGenerator generator = jsonFactory.createGenerator(new FileOutputStream("tree.json"));ObjectMapper mapper = new ObjectMapper();JsonNodeFactory factory = new JsonNodeFactory(false);//生成一个根节点ObjectNode person = factory.objectNode();//普通属性直接添加即可person.put("name", "zhangsan");person.put("age", 11);//可以生成一个对象节点,然后把这个节点加入为根节点的子节点ObjectNode address = factory.objectNode();address.put("homeAddress", "New York");address.put("workAddress", "Tokyo");person.set("address", address);//同样可以生成一个Array节点, 然后把这个Array节点加入为根节点的子节点ArrayNode friends = factory.arrayNode();ObjectNode friend1 = factory.objectNode();friend1.put("name", "weiying");ObjectNode friend2 = factory.objectNode();friend2.put("name", "caifang");friends.add(friend1).add(friend2);person.set("friends", friends);mapper.writeTree(generator, person);} }
![](/assets/blank.gif)
产生的json字符串为(我不知道在这种情况下序列化这个JSON,要是你知道请告诉我):
{"name":"zhangsan","age":11,"address":{"homeAddress":"New York","workAddress":"Tokyo"},"friends":[{"name":"weiying"},{"name":"caifang"}]}
下面将这个JSON串反序列化为一颗树,并遍历这颗树:
![](/assets/blank.gif)
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; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeType;public class JSON2Tree {public static void main(String[] args) throws JsonProcessingException, IOException {ObjectMapper mapper = new ObjectMapper();// ObjectMapper读取json,返回根节点JsonNode root = mapper.readTree(new File("tree.json"));review(root);}// 递归遍历整棵树private static void review(JsonNode root) {if (root.getNodeType().equals(JsonNodeType.OBJECT)) {Iterator<String> fieldNames = root.fieldNames();while (fieldNames.hasNext()) {String fieldName = fieldNames.next();JsonNode node = root.get(fieldName);System.out.println(fieldName);review(node);}} else if (root.getNodeType().equals(JsonNodeType.ARRAY)) {ArrayNode array = (ArrayNode) root;Iterator<JsonNode> iter = array.iterator();iter.forEachRemaining(x -> review(x));} else {System.out.println(root);}} }
![](/assets/blank.gif)
JSON <--> Json Stream
Jackson提供了一种低层次的操作json的api,简单的说,就是Jackson读取json串后,会依次将json中的每个标志都产生相应的token,例如"{"表示对象的开始,那么Jackson 就产生一个表示对象开始的token。它很强大,但是很繁琐,不推荐使用。
![](/assets/blank.gif)
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 StramParser {public static void main(String[] args) throws JsonParseException, IOException {JsonFactory factory = new JsonFactory();JsonParser parser = factory.createParser(new File("person.json"));while(!parser.isClosed()){//这里仅仅简单的打印出token的类型和值(如果有的话)JsonToken token = parser.nextToken();System.out.println(token);System.out.println(parser.getText());}} }
![](/assets/blank.gif)
![](/assets/blank.gif)
import java.io.IOException;import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator;public class StreamGenerator {public static void main(String[] args) throws IOException {JsonFactory factory = new JsonFactory();JsonGenerator generator = factory.createGenerator(System.out);// start writing with { generator.writeStartObject();generator.writeFieldName("name");generator.writeString("zhangsan");generator.writeFieldName("address");// start an array generator.writeStartArray();generator.writeStartObject();generator.writeStringField("homeAddress", "New York");generator.writeEndObject();generator.writeStartObject();generator.writeStringField("workAddress", "Tokyo");generator.writeEndObject();generator.writeEndArray();generator.writeEndObject();generator.close();} }
![](/assets/blank.gif)
Jackson详细介绍相关推荐
- Jackson使用详细介绍
Jackson使用详细介绍 一 . Jackson 介绍 二. Jackson Maven 依赖 三. ObjectMapper 对象映射器 四. Jackson JSON 基本操作 1. Jacks ...
- Canal Mysql binlog 同步至 ElasticSearch 详细介绍
文章目录 数据同步ElasticSearch 单表基本配置 适配器映射文件详细介绍(单表.多表映射介绍) 单表映射索引示例sql 单表映射索引示例sql带函数或运算操作 多表映射(一对一, 多对一)索 ...
- springboo日志t详细介绍
springboot详细介绍 序: 诞生简介 优缺点 springboot日志介绍 1.默认行为 2.自定义日志 3.不适用xml,直接使用yml或者properties配置 yml 配置: prop ...
- FRIENDS演员详细介绍
FRIENDS演员详细介绍 Jennifer Aniston Pitt (Rachel Karen Green) Jen有着希腊血统,在孩提时代曾在希腊生活过一年,因为她父亲的演艺事业全家迁到了纽约. ...
- 小熊听书项目的详细介绍
目录 一.项目概述 二.项目需求 2.1功能需求 2.2 其他需求 2.3系统功能流程图 2.4总体设计 三.开发环境 四.准备工作 五.介绍文件的存放规则 六.各部分功能的详细介绍 1.建立数据库与 ...
- HTML页面加载和解析流程详细介绍
浏览器加载和渲染html的顺序.如何加快HTML页面加载速度.HTML页面加载和解析流程等等,在本文将为大家详细介绍下,感兴趣的朋友不要错过 浏览器加载和渲染html的顺序 1. IE下载的顺序是从上 ...
- mysql为什么要压测_mysql集群压测的详细介绍
本篇文章给大家带来的内容是关于mysql集群压测的详细介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. mysql压测 mysql自带就有一个叫mysqlslap的压力测试工具,通 ...
- php比较运算符案列,PHP实例:PHP比较运算符的详细介绍
<PHP实例:PHP比较运算符的详细介绍>要点: 本文介绍了PHP实例:PHP比较运算符的详细介绍,希望对您有用.如果有疑问,可以联系我们. 比拟运算符种类 PHP实战如同它们名称所暗示的 ...
- Tempdb数据库详细介绍
Tempdb数据库详细介绍 一.Tempdb简介 tempdb是SQLServer的系统数据库一直都是SQLServer的重要组成部分,用来存储临时对象.可以简单理解tempdb是SQLServer的 ...
最新文章
- Spark的安装和使用
- 10个你必须知道的jQueryMobile代码片段
- bresenham算法画圆mfc实现_kd-tree理论以及在PCL 中的代码的实现
- gif动态图片生成器,多张图片组合后生成动图...
- 浅谈WebView利用localStore websql和IndexDB 来存储数据
- WPS有空白页老删不掉,delete和退格都删不了
- 市场车载音响麦克风摆放以及降噪解决方案
- 8051 系列单片机内部结构
- win10不让桌面上显示宽带连接服务器,Win10宽带连接不见了
- 加权有限状态转录机(Weighted Finite-State Transducer/WFST)
- 【寻找最佳小程序】11期:车来了——时时公交就在你身边,到站准确率可控制在90%以上...
- 1.0.16-Python练习题-求一张纸对折多少次能达到珠峰高度
- input-group两侧添加额外元素
- 用python爬取百科糗事的小项目
- 点云IO篇之stl文件读写
- 货币金额大写格式(银行需要)
- java 工作业绩_个人年度工作总结报告java
- 初夏,开源魔改一个带击杀音效的电蚊拍!
- Mac 显示隐藏文件 如.m2
- Flutter桌面开发 - windows插件开发
热门文章
- 草草读罢《苏菲的世界》
- 大一计算机上机试题2017,2017大一计算机基础试题及答案
- 计算机专业有哪些科研项目,计算机专业文献检索的课题有哪些
- hadoop配置文件详解系列(一)-core-site.xml篇
- 智慧城市发展新机遇,逐步从理论构想进化到实践
- GoAccess 分析nginx日志
- 2022.10.4 英语背诵
- 基于matlab的扩频通信系统建模与仿真,基于Simulink的基带数字通信系统的仿真实现...
- 使用VB 6.0使用XML和文本文件进行数据管理:第一部分
- 记录一下对接腾讯云IM的部分接口(群聊、单聊)