繁体   English   中英

Gson自定义deseralizer,用于对象中的一个变量

[英]Gson custom deseralizer for one variable in an object

我的例子:

我们有一个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" : {
   "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<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指南

我们使用数组而不是列表与GSON,并没有这样的问题:看看http://app.ecwid.com/api/v1/1003/product?id=4064 “类别”属性实际上是一个Javascript数组有一个元素。 它是这样声明的:

类别[]类别;

更新:使用TypeToken和自定义序列化可能有所帮助,请参阅此文档: https//sites.google.com/site/gson/gson-user-guide

我遇到了同样的问题。 我认为我的解决方案更简单,更通用:

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的数组没有任何问题,它会使序列化和反序列化更加简单! 不幸的是,有时候这些变化是你无法控制的。

如果您无法更改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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM