GSON:自定义对象反序列化

Cha*_*ayy 11 java android gson

好的,所以我编辑了这个问题因为它不够清楚.

编辑2:更新了JSON文件.

我在Android应用程序中使用GSON,我需要解析来自服务器的JSON文件,并且有点过于复杂.我不希望我的对象结构太重,所以我想简化内容:所以我的对象的结构将不是JSON文件的结构.

例如,如果在JSON中我有这个:

{
    "object1":{
        "attribute1" : "test1",
        "attribute40" : "test40",
        "user":{
            "id":1,
            "name":"foo"
        }
        ,"example":{
            "total":10,
            "list":[
            {
                "tag":"tag1",
                "name":"object name 1",
                "pos":1
            },
            {
                "tag":"tag10",
                "name":"object name 10",
                "pos":10
            }
        ]
        }
    }
    "object2":{
        "attribute1":"test..."
    }
}
Run Code Online (Sandbox Code Playgroud)

我不想保留我当前的对象结构,一个Example包含an ArrayListint"total"的对象.但我想只保留一个带有值的简单String "object name 1;object name 2;...".

此外,我想只存储用户ID,而不是完整的用户,因为我已经将完整的用户存储在其他地方,并且还有其他服务器API调用.

所以我的班级类似于:

class Foo{
    int userId;
    String example; //"object name 1;object name 2;..."
    ...
}
Run Code Online (Sandbox Code Playgroud)

所以我想我们可以使用自定义反序列化器实现这一点,但我找不到.我想尽可能减少内存,所以我不认为有一个完整的对象示例,然后用它来构建我String example是一种正确的方法.

在最坏的情况下,如果它太复杂,我希望能够在解析示例对象时至少只存储Tag项列表:所以我需要一个自定义反序列化器来摆脱int total.

所以我会:

class Foo{
    int userId;
    ArrayList<Tag> example;
    ...
}
Run Code Online (Sandbox Code Playgroud)

Chr*_*ipp 20

我采用了答案来呈现聊天中设计的完整解决方案,以适应更改的JSON字符串.该代码假定字符串json完全包含问题中的(更新的)JSON.要求是填写以下类(setter和toString ommitted):

class Object1
{
    private String attribute1;
    private String attribute40;
    private int userId;
    private String  nameList;
}
Run Code Online (Sandbox Code Playgroud)

GSON支持(作为大多数其他REST-libs)三种模式:

  • GSON_DOM
    通过内存读取整个JSON JsonParser.parse()并在内存中构建DOM树(对象模型访问).因此,此解决方案适用于小型JSON文件.
  • GSON_STREAM
    只读取JSON的块JsonReader.代码更复杂,但它适用于大型JSON文件.从Android 3.0 Honeycomb开始,GSON的流解析器包括在内android.util.JsonReader.
  • GSON_BIND
    通过反射直接对类进行数据绑定,可显着减少代码.GSON允许混合模式,这意味着将GSON_DOM和GSON_BIND或GSON_STREAM和GSON_BIND结合起来,这个答案应该显示出来.

要通过GSON_DOM和GSON_BIND填充Object1类,实现如下:

private static void deserializeViaObjectAccess(final String json)
{
    Gson gson = new Gson();

    // Read the whole JSON into meomory via GSON_DOM
    JsonParser parser = new JsonParser();
    JsonObject object1 = parser.parse(json).getAsJsonObject().getAsJsonObject("object1");

    // map the Object1 class via GSON_BIND
    // (bind common attributes which exist in JSON and as properties in the class)
    // mapper acts as factory
    Object1 result = gson.fromJson(object1, Object1.class);

    // manually read the attribute from the user object
    int userId = object1.getAsJsonObject("user").getAsJsonPrimitive("id").getAsInt();
    result.setUserId(userId);

    // manually read the attributes from the example object
    String names = "";
    JsonArray list = object1.getAsJsonObject("example").getAsJsonArray("list");
    for (int i = 0; i < list.size(); ++i)
    {
        JsonObject entry = list.get(i).getAsJsonObject();
        String name = entry.getAsJsonPrimitive("name").getAsString();

        names = i == 0 ? name : names + "; " + name;
    }
    result.setNameList(names);

    // Output the result
    log.debug(result.toString());
}
Run Code Online (Sandbox Code Playgroud)

要通过GSON_STREAM和GSON_BIND填充Object1类,实现如下:

目前,这只有在通过GSON_BIND或GSON_STREAM完全加载节点时才有可能.此示例需要分割节点本身.这仅适用于即将推出的2.2版本.稍后我会在GSON 2.2可用时提交代码.*