简体   繁体   English

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

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

My probelm example: 我的例子:

We have an object type of Apple. 我们有一个Apple的对象类型。 Apple has some member variables: Apple有一些成员变量:

String appleName; // The apples name
String appleBrand; // The apples brand
List<Seed> seeds; // A list of seeds the apple has

And the seed object looks as follows. 种子对象如下所示。

String seedName; // The seeds name
long seedSize; // The size of the seed

Now When I get an apple object, an apple could have more than one seed, or it could have one seed, or maybe no seeds! 现在,当我得到一个苹果对象时,一个苹果可能有一个以上的种子,或者它可能有一颗种子,或者可能没有种子!

Example JSON apple with one seed: 带有一个种子的示例JSON apple:

{
"apple" : {
   "apple_name" : "Jimmy", 
   "apple_brand" : "Awesome Brand" , 
   "seeds" : {"seed_name":"Loopy" , "seed_size":"14" }
  }
}

Example JSON apple with two seeds: 示例JSON apple有两个种子:

{
"apple" : {
   "apple_name" : "Jimmy" , 
   "apple_brand" : "Awesome Brand" , 
   "seeds" : [ 
      { 
         "seed_name" : "Loopy",
         "seed_size" : "14"
      },
      {
         "seed_name" : "Quake",
         "seed_size" : "26"
      } 
  ]}
}

Now the issue here is the first example is a JSONObject for seeds, the second example is a JSONArray for seeds. 现在问题是第一个例子是种子的JSONObject,第二个例子是种子的JSONArray。 Now I know its inconsistent JSON and the easiest way to fix it would be fix the JSON itself, but unfortunately I'm getting the JSON from some one else, so I cant fix it. 现在我知道它不一致的JSON,修复它的最简单方法是修复JSON本身,但不幸的是我从其他人那里得到了JSON,所以我无法解决它。 What would be the easiest way to fix this issue? 解决这个问题最简单的方法是什么?

You need to register a custom type adapter for the Apple type. 您需要为Apple类型注册自定义类型适配器。 In the type adapter, you will add logic to determine if you were given an array or a single object. 在类型适配器中,您将添加逻辑以确定您是否获得了数组或单个对象。 Using that info, you can create your Apple object. 使用该信息,您可以创建Apple对象。

In adition to the below code, modify your Apple model object so that the seeds field isn't automatically parsed. 在下面的代码中,修改Apple模型对象,以便不自动解析seeds字段。 Change the variable declaration to something like: 将变量声明更改为:

private List<Seed> seeds_funkyName;

Here is the code: 这是代码:

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;
    }
});

For some more info, see the Gson guide . 有关更多信息,请参阅Gson指南

We are using arrays instead of Lists with GSON, and there is no such problem: look at http://app.ecwid.com/api/v1/1003/product?id=4064 the "categories" property is actually an Javascript array with one element. 我们使用数组而不是列表与GSON,并没有这样的问题:看看http://app.ecwid.com/api/v1/1003/product?id=4064 “类别”属性实际上是一个Javascript数组有一个元素。 It was declared like this: 它是这样声明的:

Category[] categories; 类别[]类别;

UPdate: using TypeToken and Custom Serialization might help, see this doc: https://sites.google.com/site/gson/gson-user-guide 更新:使用TypeToken和自定义序列化可能有所帮助,请参阅此文档: https//sites.google.com/site/gson/gson-user-guide

I faced the same problem. 我遇到了同样的问题。 I think my solution is slightly simpler and more generic: 我认为我的解决方案更简单,更通用:

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();

Of course, I agree with the original poster, the best solution is to change the json. 当然,我同意原始海报,最好的解决方案是改变json。 There is nothing wrong with an array of size 1 and it would keep serializing and de-serializing much simpler! 大小为1的数组没有任何问题,它会使序列化和反序列化更加简单! Unfortunately, sometimes these changes are out of your control. 不幸的是,有时候这些变化是你无法控制的。

If you can't change the JSON (as you getting it from someone else) then the Simplest solution is to change your Apple and Seed class variable name in Java Class so that it matches with the parsed JSON. 如果您无法更改JSON(从其他人那里获取),那么最简单的解决方案是在Java类中更改Apple和Seed类变量名,以便它与解析的JSON匹配。

Change it to : 将其更改为:

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