zoukankan      html  css  js  c++  java
  • 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)

    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));
        }
        
        @Override
        public String toString() {
            StringBuffer sb = new StringBuffer();
            sb.append("name: " + this.name + "
    ");
            sb.append("age: " + this.age + "
    ");
            sb.append("address: " + this.address + "
    ");
            sb.append("birth: " + this.birth + "
    ");
            this.friends.forEach(x -> sb.append("friend:"+ x + "
    "));
            
            return sb.toString();
        }
    }
    public class Address {
        public String homeAddress;
        public String workAddress;
        
        //跟Person一样,我们也必须提供一个无参的默认构造器
        public Address(){}
        
        public Address(String homeAddress, String workAddress) {
            this.homeAddress = homeAddress;
            this.workAddress = workAddress;
        }
    
        @Override
        public String toString() {
            return "home:" + this.homeAddress + "  " + "work:" + this.workAddress;
        }
    }

    下面我们使用Jackson来(反)序列化 这个Person对象。

    序列化:

    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);
        }
    }

    反序列化:

    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);
        }
    }

     在上面的例子中我们看到了Jackson最基本的(反)序列化过程,下面我们介绍一些用来定制(反)序列化的注解:

    1.@JsonProperty - 在默认情况下,Jackson会处理所有public的属性和拥有getter(序列化)和setter(反序列化)的属性。但是我们可以使用 @JsonProperty来手动指定我们希望jackson处理的属性。于此同时,我们可以改变java对象映射到json中的属性名称(默认是相同的)。@JsonProperty相当于JAXB中的@XmlElement注解。

    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;
        }
        
        @Override
        public 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);
        }
    }

    2.@JsonCreator - 在上面Person的例子中,我们除了定义了一个有参数的构造器外,还必须定义一个无参的默认构造器,这是因为在反序列化的过程中,Jackson不知道该向那个有参数的构造器中传递什么参数。 我们可以在构造器上使用 @JsonCreator,并在参数列表中使用@JsonProperty,这样在反序列化时Jackson就知道该如何使用这个构造器了,这个时候我们也就没必要定义那个无参的默认构造器了。

    注意@JsonCreator仅仅在反序列化的过程中有用。

    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;
        
        @Override
        public String toString() {
            return this.name + ":" + this.age;
        }
        //在反序列化的过程中,Jackson会将json串中的name属性传递给dog_name参数, 把json串中的age属性传递给dog_age参数。
        @JsonCreator
        public 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);
        }
    }

    3.@JsonAnyGetter and @JsonAnySetter - 设想这样一种场景:除了java对象中明确指定的属性(包括使用@JsonProperty修饰指定的)外,我们希望能够随机的增加一些其他属性,让这些随机的属性也可以映射到json中去。这个时候我们就可以将这些不确定的属性放到一个map中去,并使用@JsonAnyGetter和@JsonAnySetter来修饰处理这个map的方法,然后Jackson就可以处理这些不确定的属性了。这两个属性相当于JAXB中的@XmlAnyElement和@XMLAnyAttribute。

    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<>();
        
        @JsonAnyGetter
        public Map<String, String> getAny(){
            return this.any;
        }
        
        @JsonAnySetter
        public 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));
        }
    }

    4.@JsonIgnoreProperties and @JsonIgnore - 如果我们不希望Jackson处理java对象中public的属性或者拥有getter方法的属性,我们就可以使用这两个属性来忽略它们,相当于JAXB中@XmlTransient。

    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;
        @JsonIgnore
        public 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());
        }
    
    }

    除了使用@JsonIgnoreProperties and @JsonIgnore来忽略特定属性外,还可以像下面这样忽略空的属性:

    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());
        }
    }

    5.在序列化的过程中保存类型信息

    下面定义了一个父类Animal和它的两个子类Dog和Cat,Person类有一个Animal类型的属性。

    Animal:

    import com.fasterxml.jackson.annotation.JsonCreator;
    import com.fasterxml.jackson.annotation.JsonProperty;
    
    public class Animal {
        public String name;
        public int age;
    
        @JsonCreator
        public Animal(@JsonProperty("name") String name, @JsonProperty("age") int age){
            this.name = name;
            this.age = age;
        }
    }

    Dog:

    import com.fasterxml.jackson.annotation.JsonCreator;
    import com.fasterxml.jackson.annotation.JsonProperty;
    
    public class Dog extends Animal{
        public String size;
        
        @JsonCreator
        public Dog(@JsonProperty("name") String name, @JsonProperty("age") int age, @JsonProperty("size") String size){
            super(name, age);
            this.size = size;
        }
    }

    Cat:

    import com.fasterxml.jackson.annotation.JsonCreator;
    import com.fasterxml.jackson.annotation.JsonProperty;
    
    public class Cat extends Animal{
        public String color;
        
        @JsonCreator
        public Cat(@JsonProperty("name") String name, @JsonProperty("age") int age, @JsonProperty("color") String color){
            super(name, age);
            this.color = color;
        }
    }

    Person:

    public class Person {
        public Animal animal;
    }

    我们现在为Person的animal属性设置为Dog对象,然后序列化Person对象,之后再用得到的json串反序列化。

    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());
        }
    }

    在上面的例子序列化的结果是:

    {
      "animal" : {
        "name" : "dahuang",
        "age" : 11,
        "size" : "big"
      }
    }

    在上面的结果中我们看到Jackson并没有将animal属性的具体类型信息保存下来,这样在反序列化的时候,Jackson就无法知道之前序列化时的真正类型,这就是上面反序列化后得到的是一个Animal而不是Dog的原因。

    我们修改Animal如下:

    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;
    
        @JsonCreator
        public Animal(@JsonProperty("name") String name, @JsonProperty("age") int age){
            this.name = name;
            this.age = age;
        }
    }

    然后再次执行上面那段序列化和反序列化的代码,便可以得到Person的animal属性是一个Dog对象了。 序列化的json为:

    {
      "animal" : {
        "@class" : "com.massclouds.info.Dog",
        "name" : "dahuang",
        "age" : 11,
        "size" : "big"
      }
    }

     我们看到上面的json结果中多了一个@class的属性,它就代表了animal属性的类型信息。

     当我们直接序列化一个Animal的list或者以Animal为value的map时,上面的设置依旧无法将类型信息保存到json串中,下面我们演示如何直接(反)序列化包含Animal的list和map(注意此时Animal上的注解依旧要有)。

    序列化:

    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);
        }
    }

    反序列化:

    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()));
        }
    }

    上面需要注意的地方就是 由于Class对象中是不能携带泛型信息的,所以需要使用TypeReference。

    6. Mix-in 

    当我们使用的是第三方类库中的Java类型时,我们无法直接在类型上使用注解,此时我们可以使用Jackson提供的Mix-in功能。

    我们有一个Dog类如下:

    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;
        }
    }

    我们需要定义一个抽象类,如果我们希望在Dog类的什么地方使用注解,我们就在这个抽象类中定义一个相同的声明(属性或者方法),然后使用注解,例如我们希望在Dog中的getAge方法上使用@JsonProperty注解,那么我们就在这个抽象类中定义一个名称为getAge的抽象方法,然后再在这个抽象方法上使用@JsonProperty。下面是这个抽象类的实现:

    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);
        
        @JsonCreator
        public DogMixin(@JsonProperty("dog_name") String name,@JsonProperty("dog_age") int age){
            //这里可以啥都没有。。。
        }
    }

    然后在序列化的时候,像下面这样使用,就可以跟直接在Dog类中使用注解产生一样的效果了。

    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);
        }
    }

    JSON <--> JsonNode Tree

    就如同XML的DOM树一样,我们同样可以通过一颗json节点树来构建json,当然也可以将一个json字符串反序列化为一颗节点树。

    Tree2JSON

    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);
        }
    }

    产生的json字符串为(我不知道在这种情况下序列化这个JSON,要是你知道请告诉我):

    {"name":"zhangsan","age":11,"address":{"homeAddress":"New York","workAddress":"Tokyo"},"friends":[{"name":"weiying"},{"name":"caifang"}]}

    下面将这个JSON串反序列化为一颗树,并遍历这颗树:

    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);
            }
        }
    }

     

    JSON <--> Json Stream 

    Jackson提供了一种低层次的操作json的api,简单的说,就是Jackson读取json串后,会依次将json中的每个标志都产生相应的token,例如"{"表示对象的开始,那么Jackson 就产生一个表示对象开始的token。它很强大,但是很繁琐,不推荐使用。

    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());
            }
        }
    }
    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();
        }
    }
  • 相关阅读:
    POJ 2349 Arctic Network
    OpenJudge 东方14ACM小组 / 20170123 06:Challenge 3
    OpenJudge 东方14ACM小组 / 20170123 02 岛屿
    Best Coder Lotus and Characters
    洛谷 P 1164 小A点菜
    楼房
    虫食算
    斗地主
    国王游戏
    最优贸易
  • 原文地址:https://www.cnblogs.com/zh1164/p/6808177.html
Copyright © 2011-2022 走看看