是否可以使用Gson展平JSON层次结构?

时间:2016-05-08 10:29:39

标签: java json gson

我使用Gson将JSON数据转换为Java对象。但是,JSON结构有一个可以展平的额外字段。这可能与Gson有关吗?

详细说明(因为这很难解释),JSON看起来像这样:

{
    "foo": "bar",
    "data": {
        "first": 0,
        "second": 1,
        "third": 2
    }
}

这会产生两个类,一个用于父类,一个用于data,如下所示:

public class Entry {
    private String foo;
    private Data data;
}

public class Data {
    private int first;
    private int second;
    private int third;
}

我想将data字段“压扁”到父对象中,以便Java类看起来像这样:

public class Entry {
    private String foo; 
    private int first;
    private int second;
    private int third;
}

这是否可以与Gson一起使用,例如TypeAdapters?

1 个答案:

答案 0 :(得分:0)

我将向您展示演示,并且您自己决定是否真的想要这个...因为它使TypeAdapter代码难以阅读。

private static class EntryTypeAdapter extends TypeAdapter<Entry> {
    // without registerTypeAdapter(Entry.class, new EntryTypeAdapter())
    private Gson gson = new GsonBuilder()
            // ignore "foo" from deserialization and serialization
            .setExclusionStrategies(new TestExclStrat()).create();

    @Override
    public void write(JsonWriter out, Entry value) throws IOException {
        out.beginObject();
        out.name("foo");
        out.value(value.foo);
        out.name("data");
        out.value(gson.toJson(value));
        out.endObject();
    }

    @Override
    public Entry read(JsonReader in) throws IOException {
        Entry entry = null;
        String foo = null;
        in.beginObject();
        while (in.hasNext()) {
            String name = in.nextName();
            if (name.equals("foo")) {
                foo = in.nextString();
            } else if (name.equals("data")) {
                entry = gson.fromJson(in, Entry.class);
            } else {
                in.skipValue();
            }
        }
        in.endObject();
        if(entry!= null) entry.foo = foo;
        return entry;
    }

    public class TestExclStrat implements ExclusionStrategy {
        public boolean shouldSkipClass(Class<?> arg0) {
            return false;
        }
        public boolean shouldSkipField(FieldAttributes f) {
            return f.getName().equals("foo");
        }
    }
}

可以用这个来测试:

public static void main(String[] args) throws IOException, JSONException {
    String jsonString = "{\n" +
            "    \"foo\": \"bar\",\n" +
            "    \"data\": {\n" +
            "        \"first\": 0,\n" +
            "        \"second\": 1,\n" +
            "        \"third\": 2\n" +
            "    }\n" +
            "}";

    Gson gson = new GsonBuilder()
                   .registerTypeAdapter(Entry.class, new EntryTypeAdapter()).create();
    Entry el = gson.fromJson(jsonString, Entry.class);
    String serialized = gson.toJson(el);
    System.out.println(serialized);
}

public static class Entry {
    public String foo;
    public Integer first;
    public Integer second;
    public Integer third;
}

您也可以这样做:

// even more complicated version without inner Gson help
public Entry readOption2(JsonReader in) throws IOException {
    Entry entry = new Entry();
    in.beginObject();
    while (in.hasNext()) {
        String name = in.nextName();
        if (name.equals("foo")) {
            entry.foo = in.nextString();
        } else if (name.equals("data")) {
            in.beginObject();
            while (in.hasNext()) {
                name = in.nextName();
                if (name.equals("first")) {
                    entry.first = in.nextInt();
                } else if (name.equals("second")) {
                    entry.second = in.nextInt();
                } else if (name.equals("third")) {
                    entry.third = in.nextInt();
                }else{
                    in.skipValue();
                }
            }
            in.endObject();
        } else {
            in.skipValue();
        }
    }
    in.endObject();
    return entry;
}