GSON:自定义对象序列化 [英] GSON : custom object deserialization

查看:236
本文介绍了GSON:自定义对象序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

行,所以我编辑的问题,因为它是不够清楚。

编辑2 :更新了JSON文件

我使用的Andr​​oid应用程序GSON,我需要解析JSON文件,即来自于一台服务器,是一个有点太配合。我不想让我的对象结构过于沉重,所以我想以简化内容:让我对象的结构不会是JSON文件的结构

例如,如果在JSON我有这样的:

  {
    object1:{
        ATTRIBUTE1:TEST1
        attribute40:test40,
        用户:{
            标识:1,
            名:富
        }
        ,例:{
            总:10,
            清单:
            {
                标签:标签1,
                名:对象名称1,
                POS:1
            },
            {
                标签:tag10
                名:对象名称10
                POS:10
            }
        ]
        }
    }
    Object2的:{
        ATTRIBUTE1:测试...
    }
}
 

我不希望保持我现在的对象结构,对象示例,它包含一个的ArrayList INT 总。不过,我想只保留一个简单的字符串,其值为对象名1,对象名2; ...

此外,我想只存储用户ID,不完整的使用,因为我已经有完整的用户存储在其他地方,与其他服务器API调用。

所以,我班班会是这样的:

 类Foo {
    INT用户id;
    字符串的例子; //对象名1,对象名2; ...
    ...
}
 

所以我想,我们可以用自定义解串器实现这一点,但我不觉得怎样。我想如果可能的话,尽量减少内存,所以我不认为有一个完整的对象实例,然后用它来建立我的字符串例如是一个正确的做法。

在最坏的情况下,如果它太复杂了,我希望能够存储的标签项目至少只有列表,当我解析举例对象:所以我需要一个定制的解串器摆脱掉了INT

所以,我会:

 类Foo {
    INT用户id;
    ArrayList的<标签>例;
    ...
}
 

解决方案

我通过了答案present设计的聊天,以适应变化了的JSON字符串的完整的解决方案。在code假定字符串JSON持有的问题完全(更新)JSON。要求是为了填补下面的类(setter方法​​和toString ommitted):

 类Object1
{
    私人字符串ATTRIBUTE1;
    私人字符串attribute40;
    私人诠释用户id;
    私人字符串名称列表;
}
 

GSON支持(如大多数其他的REST库)三种模式:

  • GSON_DOM
    通过读取整个JSON JsonParser.parse()并在内存中构建一个DOM树(对象模型的访问)。因此,该解决方案非常适用于小型的JSON文件。
  • GSON_STREAM
    通过 JsonReader 只读取数据块的JSON的。 code是比较复杂的,但它是适用于大型的JSON文件。由于安卓3.0蜂巢,GSON的流媒体分析器是作为 android.util.JsonReader
  • GSON_BIND
    通过反射直接数据绑定类,最大限度地减少了code significantely。 GSON允许混合模式,即结合GSON_DOM和GSON_BIND或GSON_STREAM和GSON_BIND这个答案应该显示哪些。

要填补通过GSON_DOM类Object1和GSON_BIND实施的样子:

 私有静态无效deserializeViaObjectAccess(最后弦乐JSON)
{
    GSON GSON =新GSON();

    //读取整个JSON到meomory通过GSON_DOM
    JsonParser分析器=新JsonParser();
    JSONObject的object1 = parser.parse(JSON).getAsJsonObject()getAsJsonObject(object1)。

    //映射通过GSON_BIND的Object1类
    //(绑定中存在的JSON和为属性类中的公共属性)
    //映射器作为工厂
    Object1结果= gson.fromJson(object1,Object1.class);

    //手动读取用户对象的属性
    INT用户id = object1.getAsJsonObject(用户)getAsJsonPrimitive(ID)getAsInt()。
    result.setUserId(用户id);

    //手动读取从示例对象的属性
    字符串名称=;
    JsonArray列表= object1.getAsJsonObject(例如)getAsJsonArray(名单)。
    的for(int i = 0; I<则为list.size(); ++ I)
    {
        JSONObject的条目= list.get(我).getAsJsonObject();
        字符串名称= entry.getAsJsonPrimitive(name)的符getAsString()。

        名称=我== 0?名称:姓名+,+姓名;
    }
    result.setNameList(名称);

    //输出结果
    log.debug(result.toString());
}
 

要填补通过GSON_STREAM类Object1和GSON_BIND实施的样子:

  

目前,这是唯一可能当一个节点被完全地通过GSON_BIND或装   GSON_STREAM。这个例子需要一个节点本身应该分裂。这仅仅是   可能与即将推出的2.2版本。我将手在code在后,当   GSON 2.2是可用的。*

Ok so I edited the question because it wasn't clear enough.

Edit 2 : updated the JSON file.

I'm using GSON in an Android app, and I need to parse JSON files, that come from a server, and are a little too complexes. I don't want to have my object structure too heavy, so I would like to simplify the contents : so the structure of my object won't be the structure of the JSON file.

For example, if in the JSON I have this :

{
    "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..."
    }
}

I don't want to keep in my current object structure, an object Example, that contains an ArrayList and an int "total". But I would like to keep only a simple String with the value "object name 1;object name 2;...".

Moreover, I would like to store only the user Id, not the complete User, because I already have the complete user stored somewhere else, with an other server API call.

So my class class would be something like :

class Foo{
    int userId;
    String example; //"object name 1;object name 2;..."
    ...
}

So I suppose that we can achieve this with a custom deserializer, but I don't find how. I would like if possible to minimize the memory, so I don't think that having a full object example, and then use it to build my String example is a correct way.

In the worst case, if it's too complicated, I would like to be able to store at least only the list of Tag items when I parse the Example Object : so I need a custom deserializer to get rid off the int total.

So I would have :

class Foo{
    int userId;
    ArrayList<Tag> example;
    ...
}

解决方案

I adopted the answer to present the full solution designed in chat and to fit to the changed JSON string. The code assumes that the string json holds exactly the (updated) JSON from the question. The requirement is to fill the following class (setter and toString ommitted):

class Object1
{
    private String attribute1;
    private String attribute40;
    private int userId;
    private String  nameList;
}

GSON supports (as the most other REST-libs) three modes:

  • GSON_DOM
    Reads the whole JSON via JsonParser.parse() and builds a DOM tree in memory (object model access). Therefore this solution is good for small JSON files.
  • GSON_STREAM
    Reads only chunks of the JSON via JsonReader. Code is more complicated, but it is suited for large JSON files. As of Android 3.0 Honeycomb, GSON's streaming parser is included as android.util.JsonReader.
  • GSON_BIND
    Databinding directly to classes via reflection, minimizes the code significantely. GSON allows mixed mode, which means to combine GSON_DOM and GSON_BIND or GSON_STREAM and GSON_BIND which this answer should show.

To fill the class Object1 via GSON_DOM and GSON_BIND the implementation looks like:

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

To fill the class Object1 via GSON_STREAM and GSON_BIND the implementation looks like:

At the moment, this is only possible when a node is completly loaded via GSON_BIND or GSON_STREAM. This example needs that a node itself should be splitted. This is only possible with the upcoming version 2.2. I will hand the code in later when GSON 2.2 is available.*

这篇关于GSON:自定义对象序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆