【问题标题】:How to deserialize a JSON file ( using Google JSON) consisting of same key name but uses different type?如何反序列化包含相同键名但使用不同类型的 JSON 文件(使用 Google JSON)?
【发布时间】:2020-04-17 06:29:25
【问题描述】:

考虑以下 JSON 文件:

{
    "version": "1.0",
    "firstData": {
        "meta": "this is string",
        "version": "1"
    },
    "SecondData": {
        "meta": ["string1", "string2", "string3"],
        "version": "1"
    },
    "ThirdData": {
        "meta": true,
        "version": "1"
    },
    "FourthData": {
        "meta": [true, false, false, true],
        "version": "1"
    },
    "FifthData": {
        "meta": [{
            "meta": "string",
            "version": "2"
        },
        {
            "meta": ["string1","string2"],
            "version": "2"
        }]
        "version": "1"
    }

}

正如所见,“元”属性有不同的数据类型,有时是字符串,有时是 ArrayOfString,有时是布尔等。

由于我的 JSON 文件有多个数据, 我希望它遵循以下结构:

class information
{
String version;
HashMap<String,Data> details;
}
class Data
{
 variable meta;
String version;
}

如何创建相应的 POJO 并使用 Google GSON 对其进行反序列化?

【问题讨论】:

  • 另外,关于这一点还有一些不清楚的地方,这可以用于meta 元素的任何级别的嵌套,这是一个考虑因素吗?我看到第五个元素是一个 json 对象,它也有元,这是否意味着嵌套?

标签: java json gson json-deserialization


【解决方案1】:

只需将您的meta 定义为JsonElement。然后你将有类似的排序方法:getAsString, getAsBoolean, getAsJsonObject, getAsJsonArray, ...,并且你可以在找出类型后再次反序列化它。

所以你的班级可能看起来像:

public class SomeClass {
    private int version;
    private JsonElement meta;

    //getters and setters and other stuff
}

编辑:更多阐述和实现

定义两个类:GeneralItemGeneralData

class GeneralItem
{
    public final int version;
    public final JsonElement meta;
}
class GeneralData
{
    public final String version;
    public final Map<String, GeneralItem> items;

    public GeneralData(String version, Map<String, GeneralItem> items)
    {
        this.version = version;
        this.items = items;
    }
}

然后我们为 GeneralData 定义一个自定义反序列化器:

class GeneralDataDeserializer implements JsonDeserializer<GeneralData>
{

    @Override
    public GeneralData deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
    {
        final JsonObject object = json.getAsJsonObject();
        final String version = object.get("version").getAsString();
        object.remove("version");
        HashMap<String, GeneralItem> items = new HashMap<>(object.size());
        for (Map.Entry<String, JsonElement> item : object.entrySet())
            items.put(item.getKey(), context.deserialize(item.getValue(), GeneralItem.class));
        return new GeneralData(version, items);
    }
}

最后将反序列化器注册到我们的 gson 实例并获取数据:

final Gson gson = new GsonBuilder()
        .registerTypeAdapter(GeneralData.class, new GeneralDataDeserializer())
        .create();

final String json = "your json here";
final GeneralData data = gson.fromJson(json, GeneralData.class);
System.out.println(data.items.get("firstData").meta.getAsString());
//other parts you want

(请注意,为简洁起见,删除了构造函数、getter 和 setter、错误检查等)

【讨论】:

  • 嗨 Mohammad,感谢您的回复,但我不明白。您能否详细说明一下,或者使用 GSON 分享解决方案
  • 是GSON!您只需将您的firstDataSecondData、...定义为SomeClass(将其命名为您喜欢的任何名称)然后它们将被反序列化,然后您可以为firstData 或@987654340 调用meta.getAsString() @ 代表SecondData。如果您需要更多示例,请告诉我。
  • 是的,正确的,但是如果我有 firstData,SecondData........ThousandthData..这就是为什么我不想创建这么多类,而是创建一个字符串映射到单个如上所述的类结构,你能帮我吗?
  • 如果您想查看,我提供了更多信息。 @编码器
  • 我有一个疑问,Meta 将存储为 JSONElement。如果它是一个字符串数组,它不会被存储为字符串数组。有没有办法将它们存储为相应的数据类型?
猜你喜欢
  • 1970-01-01
  • 2017-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-16
  • 1970-01-01
  • 1970-01-01
  • 2019-05-27
相关资源
最近更新 更多