gpt4 book ai didi

java - Json Multiset 与 ArrayList

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:49:07 24 4
gpt4 key购买 nike

我有 Multiset<String>对象,我将其序列化为 Json。我正在使用 Gson 执行此操作,如下所示:

Multiset<String> mset = ... ;
Gson gson = new Gson();
Files.write(Gson.toJson(mset), new File(abosulte_path_string), Charset.defaultCharset());

当我尝试反序列化它时,我会执行以下操作:

String json_string = ... // read from file
Type type = new TypeToken<Multiset<String>>(){}.getType();
Multiset<String> treated = gson.fromJson(json_string, type);

我收到这个错误:

java.lang.ClassCastException: java.util.ArrayList cannot be cast to com.google.common.collect.Multiset

当我打开 json 文件时,我看到 Multiset<String> object 确实表示为 ArrayList([string1,string2,...]),重复具有 count > 1 的字符串在多重集中。

当然,我可以将其转换为 ArrayList,然后使用 create(Iterable<>)构造函数来获取我的多重集,但这似乎是一种迂回的方式。是否有更直接的方法反序列化 json 对象以检索我的多重集?

最佳答案

编辑:在这种情况下,似乎有一种更简单的方法可以解决这个问题,即注册一个 instance creator。对于多重集:

private static class MultisetInstanceCreator implements InstanceCreator<Multiset<?>> {
@Override
public Multiset<?> createInstance(Type type) {
return HashMultiset.create();
}
}

Gson gson = new GsonBuilder()
.registerTypeAdapter(Multiset.class, new MultisetInstanceCreator())
.create();

实例创建者只是定义了应该如何创建 Multiset,因为 Guava 集合没有默认构造函数(无论如何 Multiset 是接口(interface))。

原始答案:我不确定这是否是实现您想要的效果的最佳或最简单方法,但这是我们最近解决类似问题的一种方法(在我们的案例中它正在反序列化为 ImmutableMap)。

基本思路是注册一个custom deserialiser它基本上完成了您已经发现的可能解决方案:反序列化为 ArrayList,然后将其转换为 Multiset。这里的优点是您只需注册一次自定义反序列化器,而不必到处都知道才能首先使用 ArrayList 类型。

这个自定义反序列化器看起来像这样:

private static class MultisetDeserializer implements JsonDeserializer<Multiset<?>> {
@Override
public Multiset<?> deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type[] typeArguments = parameterizedType.getActualTypeArguments();

ParameterizedType listType = new ListParameterizedType(typeArguments);
List<?> list = context.deserialize(json, listType);

return HashMultiset.create(list);
}
}

简而言之,这会将要反序列化的预期类型(例如,在您的情况下为 new TypeToken<Multiset<String>>(){}.getType())转换为 ParameterizedType 获取类型参数(在您的示例中为 String)。然后它创建一个新的 ParameterizedType,它是具有相同类型参数的 ArrayList 的类型(如下所示)。使用上下文将 JSON 反序列化为这种新类型后,您所要做的就是调用 HashMultiset.create .

ListParameterizedType看起来像这样:

private static class ListParameterizedType implements ParameterizedType {
private final Type[] typeArguments;

private ListParameterizedType(Type[] typeArguments) {
this.typeArguments = typeArguments;
}

@Override
public Type[] getActualTypeArguments() {
return typeArguments;
}

@Override
public Type getRawType() {
return ArrayList.class;
}

@Override
public Type getOwnerType() {
return null;
}
}

请注意,您可以替换 ArrayList这里几乎可以使用任何列表类,只要它具有一个类型参数和一个默认构造函数即可。

可能还有更简单的方法来实现同样的事情,例如,您可以通过检查 JsonElement 来手动进行一些解析。使用类似 isJsonArray() 的方法.这可以避免您创建一个 ArrayList,您随后会立即丢弃它。

关于java - Json Multiset 与 ArrayList,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21973141/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com