我的例子:
我们有一个Apple的对象类型。 Apple有一些成员变量:
String appleName; // The apples name
String appleBrand; // The apples brand
List<Seed> seeds; // A list of seeds the apple has
种子对象如下所示。
String seedName; // The seeds name
long seedSize; // The size of the seed
现在,当我拿到一个苹果对象时,一个苹果可能有一个以上的种子,或者它可能有一颗种子,或者可能没有种子!
带有一个种子的示例JSON apple:
{
"apple" : {
"apple_name" : "Jimmy",
"apple_brand" : "Awesome Brand" ,
"seeds" : {"seed_name":"Loopy" , "seed_size":"14" }
}
}
带有两个种子的示例JSON苹果:
{
"apple" : {
"apple_name" : "Jimmy" ,
"apple_brand" : "Awesome Brand" ,
"seeds" : [
{
"seed_name" : "Loopy",
"seed_size" : "14"
},
{
"seed_name" : "Quake",
"seed_size" : "26"
}
]}
}
现在问题是第一个例子是种子的JSONObject,第二个例子是种子的JSONArray。现在我知道它不一致的JSON,修复它的最简单方法是修复JSON本身,但不幸的是我从其他人那里得到了JSON,所以我无法解决它。解决这个问题的最简单方法是什么?
答案 0 :(得分:37)
您需要为Apple
类型注册自定义类型适配器。在类型适配器中,您将添加逻辑以确定您是否获得了数组或单个对象。使用该信息,您可以创建Apple
对象。
根据以下代码,修改Apple模型对象,以便不会自动解析seeds
字段。将变量声明更改为:
private List<Seed> seeds_funkyName;
以下是代码:
GsonBuilder b = new GsonBuilder();
b.registerTypeAdapter(Apple.class, new JsonDeserializer<Apple>() {
@Override
public Apple deserialize(JsonElement arg0, Type arg1,
JsonDeserializationContext arg2) throws JsonParseException {
JsonObject appleObj = arg0.getAsJsonObject();
Gson g = new Gson();
// Construct an apple (this shouldn't try to parse the seeds stuff
Apple a = g.fromJson(arg0, Apple.class);
List<Seed> seeds = null;
// Check to see if we were given a list or a single seed
if (appleObj.get("seeds").isJsonArray()) {
// if it's a list, just parse that from the JSON
seeds = g.fromJson(appleObj.get("seeds"),
new TypeToken<List<Seed>>() {
}.getType());
} else {
// otherwise, parse the single seed,
// and add it to the list
Seed single = g.fromJson(appleObj.get("seeds"), Seed.class);
seeds = new ArrayList<Seed>();
seeds.add(single);
}
// set the correct seed list
a.setSeeds(seeds);
return a;
}
});
有关详情,请参阅Gson guide。
答案 1 :(得分:1)
我们使用数组而不是列表与GSON,并没有这样的问题:看http://app.ecwid.com/api/v1/1003/product?id=4064“categories”属性实际上是一个带有一个元素的Javascript数组。它被宣布为:
类别[]类别;
更新:使用TypeToken和自定义序列化可能有所帮助,请参阅此文档:https://sites.google.com/site/gson/gson-user-guide
答案 2 :(得分:0)
我遇到了同样的问题。我认为我的解决方案更简单,更通用:
Gson gson = new GsonBuilder()
.registerTypeAdapter(List.class, new JsonSerializer<List<?>>() {
@Override
public JsonElement serialize(List<?> list, Type t,
JsonSerializationContext jsc) {
if (list.size() == 1) {
// Don't put single element lists in a json array
return new Gson().toJsonTree(list.get(0));
} else {
return new Gson().toJsonTree(list);
}
}
}).create();
当然,我同意原版海报,最好的解决办法是改变json。大小为1的数组没有任何问题,它会使序列化和反序列化更加简单!不幸的是,有时候这些变化是你无法控制的。
答案 3 :(得分:0)
如果您无法更改JSON(从其他人那里获取),那么最简单的解决方案是在Java类中更改Apple和Seed类变量名称,使其与解析的JSON匹配。
将其更改为:
Apple Class
-----------
String apple_name; // The apples name
String apple_brand; // The apples brand
List<Seed> seeds; // A list of seeds the apple has
And the seed object looks as follows.
Seed Class
-----------
String seed_name; // The seeds name
long seed_size; // The size of the seed