Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/216.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java GSON:自定义对象反序列化_Java_Android_Gson - Fatal编程技术网

Java GSON:自定义对象反序列化

Java GSON:自定义对象反序列化,java,android,gson,Java,Android,Gson,我编辑了这个问题,因为它不够清楚 编辑2:更新了JSON文件 我在Android应用程序中使用GSON,我需要解析JSON文件,这些文件来自服务器,有点太复杂了。我不想让我的对象结构太重,所以我想简化内容:这样我的对象结构就不会是JSON文件的结构。 例如,如果在JSON中我有: { "object1":{ "attribute1" : "test1", "attribute40" : "test40", "user":{

我编辑了这个问题,因为它不够清楚

编辑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..."
    }
}
我不想在我当前的对象结构中保留一个对象
Example
,它包含一个
ArrayList
和一个
int
“total”。但我只想保留一个值为
“object name 1;object name 2;…”
的简单字符串

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

所以我的课堂应该是这样的:

class Foo{
    int userId;
    String example; //"object name 1;object name 2;..."
    ...
}
所以我想我们可以通过自定义反序列化器来实现这一点,但我不知道如何实现。如果可能的话,我希望尽量减少内存,所以我不认为拥有一个完整的对象示例,然后用它来构建我的
字符串示例
是一种正确的方法

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

所以我会:

class Foo{
    int userId;
    ArrayList<Tag> example;
    ...
}
class-Foo{
int用户标识;
ArrayList示例;
...
}

将示例JSON反序列化为完整的示例对象,使用示例对象的名称属性构建所需内容的字符串,忘记示例对象


我并不完全理解第二个问题,但是如果您有一个完整的Test1对象,它将包含所有字段/属性,那么您可以创建一个Test2对象,它从Test1中获取它想要的字段。例如,您的Test2对象可以接受Test1作为其构造函数中的参数,并且只接受它需要的属性,而忽略其余的属性。

当您通过http在JSON中进行流式传输时,您可以简单地丢弃文本,只存储自定义对象。在这种情况下,您将不断地丢弃不需要的信息

While stream not empty  

    Read the next block into a new string

    Deserialize the string to the your object

    Store the object in a myArrayList
注意:如果您希望应用程序健壮,那么读取整个JSON并将其作为一个整体使用很可能是必要的。除非您想将JSON作为原始字符流读取(我怀疑,除非您的JSON真的非常大,否则这个快捷方式是必要的)

但无论如何,读取输入流时不必强加JSON格式良好的要求,也不必将不必要的数据结构写入内存。如果您只需要数据的一小部分,也就是说,您只需要JSON中的人名或URL,这就可以实现。但如果您想要更复杂的数据结构,它就会崩溃。然而:

//示例从JSON行解析URL,而不存储整个数据结构

While input stream is not empty

     String x = nextLine

     If x contains "http"

         myArrayList.add(parseUrl(x)
最后的想法:


但归根结底,Jsons REST请求与SQL不同——你不能随意地忽略某些字段。如果你真的想要更轻的JSON,更自然的方法是告诉或检查你的REST服务提供商是否可以简单地扩展REST请求参数的类型以适应你的用例

一个选项是使用Gson内部构建的解析器解析JSON字符串,详细说明如下。您可以这样做:

com.google.gson.JsonParser parser = new JsonParser();
JsonObject object = parser.parse(data).getAsJsonObject();
JsonObject example = object.getAsJsonObject("example");
JsonArray list = example.getAsJsonArray("list");
并且是Gson本身的一部分

使用这些函数之后,您可以使用诸如getAsInt之类的函数来解析各个字段,并构建和返回您想要的任何对象

编辑1

看起来您也可以在自定义类上使用gson.fromJson,而不仅仅是本文中给出的通用Java类型。 因此,您必须使用parse解析JSON字符串,并对其中一个内部对象或数组调用fromJson。

我建议使用库。它附带Apache许可证,因此您可以免费将其用于商业用途。 看看大写的“流式API示例”。这是非常简单的,您可以完全控制流媒体流程。所以,你可以拿走你想要的,而忽略所有其他的事情。 杰克逊图书馆被分成几个罐子。支持流式API的jar是最小的,并且不使用任何其他API。 我想这就是答案


杰克逊可以提供更多。在中,您可以找到在更高级别上读取JSON文件的方法,将其作为元素,但之前设置了需要哪些对象以及不需要哪些对象。因此,作为解析的结果,您可以立即获得所需的元素

我采纳了这个答案,以展示在chat中设计的完整解决方案,并适应更改后的JSON字符串。代码假定字符串json正好包含问题中的(更新的)json。要求填写以下类别(setter和toString未填写):

GSON支持(与大多数其他REST LIB一样)三种模式:

  • GSON_DOM
    通过
    JsonParser.parse()
    读取整个JSON,并在内存中构建DOM树(对象模型访问)。因此,此解决方案适用于小型JSON文件
  • GSON_流
    通过
    JsonReader
    只读取JSON块。代码更复杂,但它适用于大型JSON文件。从Android3.0Honeycomb开始,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());
}
private static void反序列化viaobjectaccess(最终字符串json)
{
Gson Gson=新的Gson();
//通读J
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());
}