当只关注JSON键时,使用Gson的最佳方法?

hjzp0vay  于 2023-10-18  发布在  其他
关注(0)|答案(1)|浏览(162)

想象一下,有一个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<String,JsonElement>

Map<String, JsonElement> products = gson.fromJson(rawJsonString, new TypeToken<Map<String, JsonElement>>() {}.getType());
xjreopfe

xjreopfe1#

如果你只对map键感兴趣,将map值转换为ObjectJsonElement是相当浪费的,因为即使你不使用它们,Gson仍然会构造相应的对象。你可以做的是创建一个空类,并将其指定为值类型(假设Map值总是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。这可能会更有效,如果map值不是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,在其read方法中包含上述JsonReader代码,并添加一个@JsonAdapter注解,引用该字段上的类型适配器。

相关问题