Gson使用不同对象类型的数组解析Json [英] Gson Parse Json with array with different object types

查看:167
本文介绍了Gson使用不同对象类型的数组解析Json的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何使用Gson解析这个JSON?
我有一个包含多个对象类型的数组,我不知道需要创建哪种对象才能保存此结构。我无法更改json消息(我不控制服务器)。



函数(有点)是这个的唯一类

  public class Response {
private List< Object> TR;
私人诠释结果;

(...)

}

JSON消息(请注意具有多种对象类型的数组。)

  {
tr:
[
{
a:
{
userId:112
}
},
$ bb:
{
userId:123,
地址:街道假人
}
} ,
{
a:
{
userId:154
}
}
],
results:3
}


解决方案

Gson用户手册明确涵盖了这一点:



https://sites.google.com/site/gson/gson-user-guide#TOC-Serializing-and-Deserializing -Collection-with-Objects-of-Arbitrary-Type



您有一个字段为 tr

用户指南解释说您不能直接反序列化这样的结构,并推荐:


使用Gson的解析器API(低级流解析器或DOM解析器
JsonParser)解析数组元素,然后使用Gson.fromJson()
在每个数组元素上。这是首选的方法。


在你的情况下......它将取决于该数组中可能的对象。如果他们都将拥有相同的内部对象,那么您会想要做类似...

  List< MyUserPojo> list = new ArrayList< MyUserPojo>(); 
JsonArray array = parser.parse(json).getAsJsonObject()。getAsJsonArray(tr); (JsonElement je:array)

{
Set< Map.Entry< String,JsonElement>> set = je.getAsObject()。entrySet();
JsonElement je2 = set.iterator()。next()。getValue();

MyUserPojo mup = new Gson()。fromJson(je2,MyUserPojo.class);
list.add(mup);
}

当然,这需要在您的实际自定义解串器中对象,该对象具有 tr 结果字段。

  class MyPojo 
{
List< MyUserPojo>用户列表;
int结果;
}

class MyUserPojo
{
String userId;
字符串地址;
}

类MyDeserializer实现了JsonDeserializer< MyPojo>
{
@Override
public MyPojo deserialize(JsonElement je,Type type,JsonDeserializationContext jdc)
throws JsonParseException
{
List< MyUserPojo> list = new ArrayList< MyUserPojo>();
JsonArray array = je.getAsJsonObject()。getAsJsonArray(tr); (JsonElement je2:array)

{
Set< Map.Entry< String,JsonElement>> set = je2.getAsObject()。entrySet();
JsonElement je3 = set.iterator()。next()。getValue();

MyUserPojo mup = new Gson()。fromJson(je3,MyUserPojo.class);
list.add(mup);
}

MyPojo mp = new MyPojo();
mp.tr = list;
mp.results = je.getAsObject()。getAsJsonPrimitive(results)。getAsInt();

return mp;


$ / code $ / pre

现在你全都设定了 - 你可以使用反序列化器并创建你的对象:

$ pre $ g $ g $ gson = new GsonBuilder()
.registerTypeAdapter(MyPojo.class,new MyDeserializer ())
.build();

MyPojo mp = gson.fromJson(json,MyPojo.class);

如果 a b 等都很重要......好吧,你必须弄清楚。但是上面的内容会让你很好地理解处理你的JSON结构需要什么。

为了完整起见,围绕这个唯一的哈克方式是,如果这些类型的数量相当有限,并且内部对象在它的方面也相当有限领域。您可以创建一个包含所有可能性的POJO:

  class MyPojo 
{
MySecondPojo a;
MySecondPojo b;
...
MySecondPojo f;
}

class MySecondPojo
{
String userId;
字符串地址;
...
字符串someOtherField;
}

当Gson反序列化JSON时,它会设置POJO中缺少的字段,到 null 。你现在可以在你的POJO中拥有 tr List 或这些数组。再次强调一下,这真的很诡异,而且是错误的做法,但我想我会解释直接解析该数组需要做什么。

How can I parse this JSON using Gson? I have an array with multiple object types and I don't know what kind of object I need to create to save this structure. I cannot change the json message (I don't control the server).

The only class that function (sort of) was this

public class Response {
    private List<Object> tr;
    private int results;

    (...)

}

JSON Message (Note the array with multiple object types.)

{
   "tr":
   [
       {
           "a":
           {
               "userId": "112"
           }
       },
       {
           "b":
           {
               "userId": "123",
               "address":"street dummy" 
           }
       },
       {
           "a":
           {
               "userId": "154"
           }
       }
   ],
"results":3
}

解决方案

The Gson User's Guide explicitly covers this:

https://sites.google.com/site/gson/gson-user-guide#TOC-Serializing-and-Deserializing-Collection-with-Objects-of-Arbitrary-Types

You have an object with a field tr that is an array containing arbitrary types.

The users guide explains that you can't directly deserialize such a structure, and recomends:

Use Gson's parser API (low-level streaming parser or the DOM parser JsonParser) to parse the array elements and then use Gson.fromJson() on each of the array elements. This is the preferred approach.

In your case ... it would really depend on what objects were possible in that array. If they are all going to have that same inner object you'd want to do something like...

List<MyUserPojo> list = new ArrayList<MyUserPojo>();
JsonArray array = parser.parse(json).getAsJsonObject().getAsJsonArray("tr");
for (JsonElement je : array)
{
    Set<Map.Entry<String,JsonElement>> set = je.getAsObject().entrySet();
    JsonElement je2 = set.iterator().next().getValue();

    MyUserPojo mup = new Gson().fromJson(je2, MyUserPojo.class);
    list.add(mup);
}

And of course, this would need to be inside a custom deserializer for your actual object that would have the tr and results fields.

class MyPojo
{
    List<MyUserPojo> userList;
    int results; 
}

class MyUserPojo
{
    String userId;
    String address;
}

class MyDeserializer implements JsonDeserializer<MyPojo>
{
    @Override
    public MyPojo deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
                              throws JsonParseException
    {
        List<MyUserPojo> list = new ArrayList<MyUserPojo>();
        JsonArray array = je.getAsJsonObject().getAsJsonArray("tr");
        for (JsonElement je2 : array)
        {
            Set<Map.Entry<String,JsonElement>> set = je2.getAsObject().entrySet();
            JsonElement je3 = set.iterator().next().getValue();                 

            MyUserPojo mup = new Gson().fromJson(je3, MyUserPojo.class);
            list.add(mup);
        }

        MyPojo mp = new MyPojo();
        mp.tr = list;
        mp.results = je.getAsObject().getAsJsonPrimitive("results").getAsInt();

        return mp;
    }
}

Now you're all set - you can use that deserializer and create your object:

Gson gson = new GsonBuilder()
                .registerTypeAdapter(MyPojo.class, new MyDeserializer())
                .build();

MyPojo mp = gson.fromJson(json, MyPojo.class);

If the a, b etc are important ... well, you'll have to figure that out. But the above should get you well on your way to understanding what's going to be needed to deal with your JSON structure.

For completeness sake, the only "hacky" way around this is if there is a fairly limited number of those types and the inner object also is fairly limited in terms of its fields. You could create a POJO that encompasses all the possibilities:

class MyPojo 
{
    MySecondPojo a;
    MySecondPojo b;
    ...
    MySecondPojo f;
}

class MySecondPojo
{
    String userId;
    String address;
    ...
    String someOtherField;
}

When Gson deserializes JSON it will set any missing fields in your POJO(s) to null. You could now have tr be a List or array of these in your POJO. Again and to emphasize, this is really quite hacky and the wrong way to do it, but I thought I'd explain what would be required to directly parse that array.

这篇关于Gson使用不同对象类型的数组解析Json的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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