首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Gson序列化Iterable<Map.Entry<>>

用Gson序列化Iterable<Map.Entry<>>
EN

Stack Overflow用户
提问于 2019-03-24 14:27:20
回答 1查看 407关注 0票数 1

我试图用google库序列化Map.Entry类型中的"Iterable“--并且得到了一个空输出。

这里是一个代码示例:

代码语言:javascript
复制
static private Iterable<Map.Entry<String, Integer>> getIterable(){
    HashMap<String, Integer> map = new HashMap<>();
    map.put("1", 1);
    map.put("2", 2);

    Iterable<Map.Entry<String, Integer>> iterable = map.entrySet();
    return  iterable;

}

public static void main(String[] args) {

    Iterable<Map.Entry<String, Integer>> myIterable = getIterable();
    GsonBuilder builder = new GsonBuilder();
    Gson gson = builder.enableComplexMapKeySerialization().create();
    String  a= gson.toJson(myIterable);
    System.out.println(a);

}

这是输出:

{},{}

知道我做错了什么吗?

谢谢:)

java版本: 1.8

gson版本: 2.6.2

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-24 14:38:00

一个更干净的方法可能是

代码语言:javascript
复制
final Iterable<Entry<String, Integer>> iterable = getIterable();
final Gson gson = new Gson();
final JsonArray jsonArray = new JsonArray();

for (final Entry<String, Integer> entry : iterable) {
    final JsonElement jsonElement = gson.toJsonTree(entry);
    jsonElement.getAsJsonObject().remove("hash");
    jsonArray.add(jsonElement);
}

或者我喜欢的Stream版本

代码语言:javascript
复制
StreamSupport.stream(iterable.spliterator(), false)
             .map(gson::toJsonTree)
             .map(JsonElement::getAsJsonObject)
             .peek(obj -> obj.remove("hash"))
             .collect(of(
                     JsonArray::new,
                     (array, obj) -> array.add(obj),
                     (output, toMerge) -> {
                         output.addAll(toMerge);
                         return output;
                     }
             ));

输出:[{"key":"1","value":1},{"key":"2","value":2}]

TL;DR:您需要自定义TypeAdapterFactory 需要自定义TypeAdapter

TypeAdapters上查看此方法

代码语言:javascript
复制
public static <TT> TypeAdapterFactory newFactory(
    final TypeToken<TT> type, final TypeAdapter<TT> typeAdapter) {
  return new TypeAdapterFactory() {
    @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
    @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
      return typeToken.equals(type) ? (TypeAdapter<T>) typeAdapter : null;
    }
  };
}

没有自定义的TypeAdapterFactory

代码语言:javascript
复制
typeToken.equals(type)

返回false,甚至不使用自定义TypeAdapter<Entry>

问题就在这里,在ReflectiveTypeAdapterFactory#write

代码语言:javascript
复制
@Override public void write(JsonWriter out, T value) throws IOException {
  if (value == null) {
    out.nullValue();
    return;
  }

  out.beginObject();
  try {
    for (BoundField boundField : boundFields.values()) {
      if (boundField.writeField(value)) {
        out.name(boundField.name);
        boundField.write(out, value);
      }
    }
  } catch (IllegalAccessException e) {
    throw new AssertionError(e);
  }
  out.endObject();
}

ReflectiveTypeAdapterFactory#getBoundFields

代码语言:javascript
复制
private Map<String, BoundField> getBoundFields(Gson context, TypeToken<?> type, Class<?> raw) {
  Map<String, BoundField> result = new LinkedHashMap<String, BoundField>();

  if (raw.isInterface()) {
    return result;
  }

Gson将输入Entry (Class<?> raw参数)识别为

代码语言:javascript
复制
interface Map.Entry<K, V> { ... }

因此

代码语言:javascript
复制
if (raw.isInterface())

产生true,然后返回一个空的boundFields LinkedHashMap

因此,在这里

代码语言:javascript
复制
for (BoundField boundField : boundFields.values()) { ... }

没有执行循环,也没有提取和写入任何值

代码语言:javascript
复制
boundField.write(...)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55324814

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档