反序列化json时跳过根元素

时间:2012-08-17 10:48:36

标签: java json gson

如何反序列化以下JSON以跳过根元素并仅解析此JSON的内部部分。我想避免创建额外的第3课Root,其中只包含MapWrapper字段。

{
    "root": {
        "language": "en",
        "map": {
            "k1": {
                "name": "n1",
            },
            "k2": {
                "name": "n2",
            }
        }
    }
}

所以我想只有这两个类:

class MapWrapper {
    private String language;
    private Map<String, MyMapEntry> map;
}

class MyMapEntry {
    String name;
}

4 个答案:

答案 0 :(得分:3)

考虑以下JSON:

{"authorization":{"username":"userabc", "password":"passabc"}}

没有根元素的此JSON的DTO

public class Authorization {
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    // Add a container for the root element
    public static class Container {
        public Authorization authorization;
    }
}

使用以下方法从/转换为JSON(您可以将其保留在DTO或其他帮助类中)

public String toJson(Authorization authorization) {
    Gson gson = new Gson();
    Authorization.Container container = new Authorization.Container();
    container.authorization = authorization;
    return gson.toJson(container);
}

public Authorization fromJson(String json) {
    Gson gson = new Gson();
    Authorization.Container container = gson.fromJson(json, Authorization.Container.class);
    return container.authorization;
}

答案 1 :(得分:2)

我的答案迟到了。

一旦我们解析了Json,容器总是成为JsonElement的JsonObject子类。因此,如果我们想跳过它,我们只需要将它转换为它的子类并抓住保存内部类的字段。

    String response = ....;

    Gson gson = new Gson();

    JsonParser p = new JsonParser();
    JsonElement jsonContainer = p.parse(response);
    JsonElement jsonQuery = ((JsonObject) jsonContainer).get("query");

    MyQuery query = gson.fromJson(jsonQuery, MyQuery.class);

注意:JsonObject和JSONObject是不同的类(使用com.google.Json导入)。

您可以更多地概括这个答案,这样您就不需要知道内部类的名称。您只需获取容器对象的唯一字段即可。但是,除了启动迭代器之外我没有办法做到这一点,没有我能看到的getValue(atIndex)方法,我认为启动迭代器可能不如简单地按名称查找字段(但可能是错)。

迭代器方法如下:

    JsonElement jsonQuery = ((JsonObject) jsonContainer).entrySet().iterator()
                            .next().getValue();

答案 2 :(得分:0)

您可以将其反序列化为Map<String, MapWrapper>

答案 3 :(得分:0)

受Gustav Carlson的想法启发,我决定将其扩展为具体样本。这是一个junit测试,用于测试将此JSON解析为Map。

public static class MapWrapper {
    private String language;
    private Map<String, MyMapEntry> map;
}

public static class MyMapEntry {
    String name;
}

@Test
public void testParsing() {
    String json = "{\n" +
            "    \"root\": {\n" +
            "        \"language\": \"en\",\n" +
            "        \"map\": {\n" +
            "            \"k1\": {\n" +
            "                \"name\": \"n1\"\n" +
            "            },\n" +
            "            \"k2\": {\n" +
            "                \"name\": \"n2\"\n" +
            "            }\n" +
            "        }\n" +
            "    }\n" +
            "}";
    Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
    Type type = new TypeToken<Map<String, MapWrapper>>(){}.getType();
    Map<String, MapWrapper> parsed = gson.fromJson(json, type);
    MapWrapper mapWrapper = parsed.get("root");
    Assert.assertEquals("en", mapWrapper.language);
    Assert.assertEquals("n2", mapWrapper.map.get("k2").name);
}