Gson嵌套对象问题

时间:2013-10-09 21:20:34

标签: json gson

将Gson 2.2.4与嵌套对象和JsonReader一起用于流式传输。

JSON:

{
"name": "David",
"address": {
    "city": "Bangalore"
},
"role": "Manager"
}

POJO课程:

public class Data {

    private String name;
    private String role;
    private Address address;

    public String getRole() {
        return role;
    }
    public void setRole(String role) {
        this.role = role;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Address getAddress() {
        return address;
    }
    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    public String toString(){
        return getName() + "::"+getRole()+"::"+getAddress().getCity();
    }
}


public class Address {

    private String city;

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

}

我的代码:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;

public class TestReader {

    public static void main(String[] args) throws IOException {
        InputStream is = new FileInputStream("test.txt");
        InputStreamReader isr = new InputStreamReader(is);

        JsonReader reader = new JsonReader(isr);

        Data data = new Data();
        data.setAddress(new Address());
        String key = null;

        while (reader.hasNext()) {
            JsonToken token = reader.peek();

            switch (token) {
            case BEGIN_OBJECT:
                reader.beginObject();
                break;
            case END_OBJECT:
                reader.endObject();
                break;
            case BEGIN_ARRAY:
                reader.beginArray();
                break;
            case END_ARRAY:
                reader.endArray();
                break;
            case NAME:
                key = reader.nextName();
                break;
            case STRING:
                if ("name".equals(key))
                    data.setName(reader.nextString());
                else if ("role".equals(key))
                    data.setRole(reader.nextString());
                else if ("city".equals(key))
                    data.getAddress().setCity(reader.nextString());
                break;
            case NULL:
                reader.nextNull();
                break;
            case END_DOCUMENT:
                break;
            default:
                break;

            }
        }
        reader.close();

        System.out.println(data);
    }
}

它打印“David :: null :: Bangalore”并且无法在嵌套对象之后解析任何内容。如果我将JSON更改为

{
"name": "David",
"role": "Manager",
"address": {
    "city": "Bangalore"
}
}

它工作正常并打印“David :: Manager :: Bangalore”。尝试了很多,但不确定我错过了什么。

1 个答案:

答案 0 :(得分:2)

由于JSON本质上是递归的,因此您的方法也应如此。那就是你需要再次调用Address对象而不是Data。

所以我修复了你的代码(我管理它,以一种天真的方式)来处理这个特定的情况。如果你有一个更复杂的结构,当然方法也会变得更复杂。

package stackoverflow.questions.q19282973;

import java.io.*;

import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;

public class TestReader {

    public static void main(String[] args) throws IOException {
        String json = "{\"name\": \"David\",\"address\": {\"city\": \"Bangalore\"},\"role\": \"Manager\"}";
        String json2 = "{\"name\": \"David\",\"role\": \"Manager\",\"address\": {\"city\": \"Bangalore\"}}";

        InputStream is = new ByteArrayInputStream(json2.getBytes("UTF-8"));
        InputStreamReader isr = new InputStreamReader(is);

        JsonReader reader = new JsonReader(isr);

        Data data = new Data();
        data.setAddress(new Address());
        String key = null;

        key = read(reader, data, key);
        reader.close();

        System.out.println(data);
    }

    private static String read(JsonReader reader, Object obj, String key)
            throws IOException {


        while (reader.hasNext()) {
            JsonToken token = reader.peek();

            switch (token) {
            case BEGIN_OBJECT:
                reader.beginObject();
                if ("address".equals(key)) {

                    while (reader.hasNext()) {
                        read(reader, ((Data) obj).getAddress(), key);
                    }
                    reader.endObject();
                }
                break;
            case END_OBJECT:
                reader.endObject();
                break;
            case BEGIN_ARRAY:
                reader.beginArray();
                break;
            case END_ARRAY:
                reader.endArray();
                break;
            case NAME:
                key = reader.nextName();
                break;
            case STRING:
                if (obj instanceof Data) {
                    Data data = (Data) obj;
                    if ("name".equals(key))
                        data.setName(reader.nextString());
                    else if ("role".equals(key))
                        data.setRole(reader.nextString());
                }
                if (obj instanceof Address) {
                    Address address = (Address) obj;
                    if ("city".equals(key))
                        address.setCity(reader.nextString());
                }
                break;
            case NULL:
                reader.nextNull();
                break;
            case END_DOCUMENT:
                break;
            default:
                break;

            }
        }
        return key;
    }
}

为什么要使用JsonReader ?它应该只用于特定情况,任何情况下它都是一个非常低级别的Gson类。

你只需要这样的东西

Data d = new Gson().fromJson(yourJsonString, Data.class) to parse.

或者,如果您只想解析JSON的特定部分,可以编写自己的反序列化器。