如何使用Gson解析此JSON? 我有一个包含多个对象类型的数组,我不知道为了保存这个结构我需要创建什么样的对象。我无法更改json消息(我不控制服务器)。
唯一有功能(类别)的类是
public class Response {
private List<Object> tr;
private int results;
(...)
}
JSON消息(请注意具有多种对象类型的数组。)
{
"tr":
[
{
"a":
{
"userId": "112"
}
},
{
"b":
{
"userId": "123",
"address":"street dummy"
}
},
{
"a":
{
"userId": "154"
}
}
],
"results":3
}
答案 0 :(得分:20)
Gson用户指南明确涵盖了这一点:
您有一个字段tr
的对象,它是一个包含任意类型的数组。
用户指南解释说您无法直接反序列化此类结构,并建议:
使用Gson的解析器API(低级流解析器或DOM解析器 JsonParser)解析数组元素然后使用Gson.fromJson() 在每个数组元素上。这是首选方法。
在你的情况下......它真的取决于该数组中可能的对象。如果他们都将拥有相同的内部对象,那么你会想做一些像......
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);
}
当然,这需要位于具有tr
和results
字段的实际对象的自定义反序列化器中。
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;
}
}
现在你已经完成了 - 你可以使用该反序列化器并创建你的对象:
Gson gson = new GsonBuilder()
.registerTypeAdapter(MyPojo.class, new MyDeserializer())
.build();
MyPojo mp = gson.fromJson(json, MyPojo.class);
如果a
,b
等重要......好吧,你必须弄明白。但是上面的内容可以帮助您了解处理JSON结构所需的内容。
为了完整起见,唯一的“hacky”方法是,如果这些类型的数量相当有限,并且内部对象在其字段方面也相当有限。您可以创建一个包含所有可能性的POJO:
class MyPojo
{
MySecondPojo a;
MySecondPojo b;
...
MySecondPojo f;
}
class MySecondPojo
{
String userId;
String address;
...
String someOtherField;
}
当Gson反序列化JSON时,它会将您的POJO中的任何缺失字段设置为null
。您现在可以在POJO中将tr
设为List
或其中一组。再次强调,这真的很hacky并且做错了,但我想我会解释直接解析该数组所需的内容。
答案 1 :(得分:4)
我从每个答案中选择一些东西,然后这样做:
响应对象
public class Response {
private List<Users> tr;
private int results;
(...)
}
通用用户
public class User {
public static final int TYPE_USER_A =0;
public static final int TYPE_USER_B =1;
private String userId;
private int type;
(...)
}
<强> A 强>
public class a extends User {
private String location;
(...)
}
B
public class b extends User {
private String adress;
(...)
}
解析方法
private Response buildResponseObject(String response) {
Response tls = new Response();
List<Users> users = new ArrayList<users>();
User u;
try {
JSONObject object = new JSONObject(response);
tls.setResults(object.getInt("results"));
JSONArray array = object.getJSONArray("tr");
for (int i = 0; i < array.length(); i++) {
JSONObject trs = array.getJSONObject(i);
if (trs.has("a")) {
String json = trns.getString("a");
A a = new Gson().fromJson(json,A.class);
a.setType(User.TYPE_USER_A);
users.add(a);
} else if (trs.has("b")) {
String json = trs.getString("b");
B b= new Gson().fromJson(json,B.class);
B.setType(User.TYPE_USER_B);
users.add(b);
}
}
tls.setUsers(users);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return tls;
}
这不像我想的那么优雅,将原生JsonObjects与Gson方法混合,但对我有用。
答案 2 :(得分:2)
请在此处试用此代码:
public class Address {
public String userId;
public String address;
// ...
}
public class Response {
private HashMap<String, Address> tr;
private int results;
// ...
}
用法:
String json = "{\n \"tr\":\n {\n \"a\": {\n \"userId\": \"112\"\n },\n \"b\": {\n \"userId\": \"123\",\n \"address\":\"street dummy\"\n },\n \"c\": {\n \"userId\": \"154\"\n }\n },\n \"results\":3\n}";
Response users = new Gson().fromJson(json, Response.class);
正如您所看到的,我需要修改结构:
{
"tr":
{
"a": {
"userId": "112"
},
"b": {
"userId": "123",
"address":"street dummy"
},
"c": {
"userId": "154"
}
},
"results":3
}
但不幸的是,我没有设法允许多个密钥。现在我不知道如何解决这个问题。
答案 3 :(得分:0)
我认为此链接可能对您有所帮助: https://sites.google.com/site/gson/gson-user-guide#TOC-Collections-Examples
基本上,为你的“对象”(我想用的那种用户)创建一个类,然后使用Gson的反序列化代码,如下所示:
Type collectionType = new TypeToken<Collection<User>>(){}.getType();
Collection<User> users= gson.fromJson(json, collectionType);
答案 4 :(得分:-2)
您可以为json对象创建相应的java类。整数,字符串值可以按原样映射。 Json可以这样解析 -
Gson gson = new GsonBuilder().create();
Response r = gson.fromJson(jsonString, Response.class);
以下是一个示例 - http://rowsandcolumns.blogspot.com/2013/02/url-encode-http-get-solr-request-and.html