Gson自定义deseralizer,用于对象中的一个变量
我的例子:
我们有一个Apple的对象类型。 Apple有一些成员变量:
String appleName; // The apples name String appleBrand; // The apples brand List 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" : { "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,所以我无法解决它。 解决这个问题最简单的方法是什么?
您需要为Apple
类型注册自定义类型适配器。 在类型适配器中,您将添加逻辑以确定您是否获得了数组或单个对象。 使用该信息,您可以创建Apple
对象。
在下面的代码中,修改Apple模型对象,以便不自动解析seeds
字段。 将变量声明更改为:
private List seeds_funkyName;
这是代码:
GsonBuilder b = new GsonBuilder(); b.registerTypeAdapter(Apple.class, new JsonDeserializer() { @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 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>() { }.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 (); seeds.add(single); } // set the correct seed list a.setSeeds(seeds); return a; } });
有关更多信息,请参阅Gson指南 。
我们使用数组而不是列表与GSON,并没有这样的问题:看http://app.ecwid.com/api/v1/1003/product?id=4064 “类别”属性实际上是一个Javascript数组有一个元素。 它被声明如下:
类别[]类别;
更新:使用TypeToken和自定义序列化可能有所帮助,请参阅此文档: https : //sites.google.com/site/gson/gson-user-guide
如果您无法更改JSON(从其他人那里获取),那么最简单的解决方案是在Java类中更改Apple和Seed类变量名,以便它与解析的JSON匹配。
将其更改为:
Apple Class ----------- String apple_name; // The apples name String apple_brand; // The apples brand List 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
我遇到了同样的问题。 我认为我的解决方案更简单,更通用:
Gson gson = new GsonBuilder() .registerTypeAdapter(List.class, new JsonSerializer>() { @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的数组没有任何问题,它会使序列化和反序列化更加简单! 不幸的是,有时候这些变化是你无法控制的。
- GSON:使用ReflectiveTypeAdapterFactory.Adapter序列化/反序列化具有已注册类型层次结构适配器的类的对象
- 使用Java(Jackson)读取JSON中嵌套键的值
- 如何从自定义Gson JsonSerializer调用另一个序列化程序?
- Java:在Applet中使用Gson会导致SecurityException
- 如何使用Google / GSON将JSON字符串转换为Java POJO?
- 为什么Gson fromJson抛出一个JsonSyntaxException:预期BEGIN_OBJECT但是BEGIN_ARRAY?
- 用gson解析JSON数组
- 序列化接口列表GSON
- 使用Gson反序列化通用集合