用于对象中一个变量的 Gson 自定义解串器

发布于 2024-11-07 18:54:33 字数 1030 浏览 0 评论 0原文

我的问题示例:

我们有一个 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_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,所以我无法修复它。解决这个问题最简单的方法是什么?

My probelm example:

We have an object type of Apple. Apple has some member variables:

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:

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

Example JSON apple with two seeds:

{
"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. 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. What would be the easiest way to fix this issue?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

∞觅青森が 2024-11-14 18:54:33

您需要为 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 指南

You need to register a custom type adapter for the Apple type. 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.

In adition to the below code, modify your Apple model object so that the seeds field isn't automatically parsed. 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.

眉黛浅 2024-11-14 18:54:33

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

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

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. There is nothing wrong with an array of size 1 and it would keep serializing and de-serializing much simpler! Unfortunately, sometimes these changes are out of your control.

長街聽風 2024-11-14 18:54:33

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

类别[]类别;

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

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. 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

堇年纸鸢 2024-11-14 18:54:33

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

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.

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文