仅关心 JSON 键时利用 Gson 的最佳方法?

问题描述 投票:0回答:1

想象一下,有一个 JSON 结构,其中包含客户购买的产品列表:

{
  "product_key_1": {
    "name": "product_name_1",
    "price": 10.99
  },
  "product_key_2": {
    "name": "product_name_2",
    "price": 24.99
  },
  "product_key_3": {
    "name": "product_name_3",
    "price": 7.49
  }
}

但是,在这种情况下,客户端只对提取代表产品的密钥感兴趣,而不关心产品名称或价格等具体细节。

使用 Gson 反序列化此 JSON 字符串的推荐方法是什么,主要目标是获取密钥?

目前我正在采用以下方法:

Map<String, Object> products = gson.fromJson(rawJsonString, Object.class);
Set<String> productKeys = products.keySet(); 

这可行,但我想知道这是否是正确的方法。”

编辑: 似乎另一种方法是将 json 转换为 Map

Map<String, JsonElement> products = gson.fromJson(rawJsonString, new TypeToken<Map<String, JsonElement>>() {}.getType());
gson deserialization
1个回答
0
投票

如果你只对地图键感兴趣,那么将地图值反序列化为

Object
JsonElement
是相当浪费的,因为Gson仍然会构造相应的对象,即使你不使用它们。 您可以做的是创建一个空类并将其指定为值类型(假设映射值始终为 JSON 对象类型)。因为 Gson 默认情况下会忽略未知字段,所以它将有效地跳过 JSON 对象成员值中的所有字段。

代码可能如下所示:

class IgnoredValue {
}
Map<String, IgnoredValue> map = gson.fromJson(rawJsonString, new TypeToken<Map<String, IgnoredValue>>() {});
System.out.println(map.keySet());

此外,您还可以为值类型注册自定义

TypeAdapter
,它始终会跳过 JSON 值并返回
null
。如果映射值不是 JSON 对象(例如 JSON 数组、数字或字符串),这可能会更有效,并且也可以工作:

Gson gson = new GsonBuilder()
    .registerTypeAdapter(IgnoredValue.class, new TypeAdapter<IgnoredValue>() {
        @Override
        public IgnoredValue read(JsonReader in) throws IOException {
            in.skipValue();
            return null;
        }
        @Override
        public void write(JsonWriter out, IgnoredValue value) throws IOException {
            throw new UnsupportedOperationException();
        }
    })
    .create();
Map<String, IgnoredValue> map = gson.fromJson(rawJsonString, new TypeToken<Map<String, IgnoredValue>>() {});

或者,如果此 JSON 数据位于顶层(并且没有深深嵌套在较大的 JSON 文档中),那么如果您愿意,您也可以直接使用

JsonReader

List<String> keys = new ArrayList<>();
try (JsonReader jsonReader = new JsonReader(new StringReader(rawJsonString))) {
    jsonReader.beginObject();

    // Handle all JSON object members
    while (jsonReader.hasNext()) {
        keys.add(jsonReader.nextName());
        jsonReader.skipValue();
    }

    jsonReader.endObject();
}

如果 JSON 数据嵌套得很深,并且您有一个封闭的反序列化类,那么您可以添加一个

List<String> products
字段,创建一个
TypeAdapter
,其中在其
JsonReader
方法中包含上述
read
代码,然后添加一个
@JsonAdapter
注释引用该字段上的类型适配器。

© www.soinside.com 2019 - 2024. All rights reserved.