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

 

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM