Gson被读入LinkedTreeMap

时间:2016-12-12 16:40:30

标签: java json generics

我在序列化JSON数据时遇到了麻烦。

所以,我正在尝试使用泛型,但是当我尝试实现它时,Gson不知怎么讨厌我。 我所要做的就是用泛型进行基本的抽象。 这是我的代码:

执行泛型部分的主要类:

package com.yasinyazici.riot.config.json;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Map;

public abstract class JsonDataParser<T> {
    protected Gson gson = new Gson();
    protected String json;

    public JsonDataParser(String json) {
        this.json = json;
    }

    protected Map<String, T> transform() {
        Type type = new TypeToken<Map<String, T>>(){}.getType();
        return gson.fromJson(json, type);
    }

    public abstract T get();
}

这是主要班级的孩子:

package com.yasinyazici.riot.config.json.impl;

import com.yasinyazici.riot.config.json.JsonDataParser;
import com.yasinyazici.riot.data.summoner.SummonerProperties;

public class SummonerPropertiesParser extends JsonDataParser<SummonerProperties> {
    public SummonerPropertiesParser(String json) {
        super(json);
    }

    @Override
    public SummonerProperties get() {
        transform().entrySet().forEach(p -> System.out.println(p.getValue().getProfileIconId()));
        return null;
    }
}

如您所见,IntelliJ甚至将#get()识别为“SummonerProperties”。

这是我的错误:

Exception in thread "main" java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.yasinyazici.riot.data.summoner.SummonerProperties
    at com.yasinyazici.riot.config.json.impl.SummonerPropertiesParser.lambda$get$0(SummonerPropertiesParser.java:17)
    at java.lang.Iterable.forEach(Iterable.java:75)
    at com.yasinyazici.riot.config.json.impl.SummonerPropertiesParser.get(SummonerPropertiesParser.java:17)
    at com.yasinyazici.riot.Main.main(Main.java:16)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

我有点困惑。如果我打印p(对象本身),我会以一些奇怪的格式获得json

jungleíslife={id=8.2249757E7, name=Jungle ís Life, profileIconId=1339.0, summonerLevel=30.0, revisionDate=1.481558959E12}

原始json看起来像这样:

{"jungleíslife":{"id":82249757,"name":"Jungle ís Life","profileIconId":1339,"summonerLevel":30,"revisionDate":1481558959000}}

p#getValue()打印json的主体。 (以奇怪的格式)

所以似乎某些东西没有被正确解析。

任何?非常感谢任何帮助/解决方案。

编辑:这不完全是重复的,原因是我不是要尝试参数化任何类型,而是需要获取原始类型(我没有使用任何类用于访问类字段以进行解析的变量,我也不想这样做。

EDIT2:好的,好的。嗯,我尝试了选项1的示例(请参阅链接问题作为参考),但我得到以下内容(请注意,我在ListParameterizedType类中使用#getRawType()方法返回Map.class):

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1

即使我让它继续返回ArrayList,它也会引发我的注意:

Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

编辑:仍有问题......

EDIT2:没有人有可能的解决方案..?

1 个答案:

答案 0 :(得分:2)

您必须在子类中构造TypeToken,其中具体类型信息可用。向您的超类添加一个抽象方法:

protected abstract Type getType();

更改解析方法以使用它:

protected Map<String, T> transform() {
    return gson.fromJson(json, getType());
}

然后在子类中重写getType以返回具体类型:

@Override
protected Type getType() {
    return new TypeToken<Map<String, SummonerProperties>>(){}.getType();
}

不相关,但您在打印getValue()时看到的“怪异格式”不是json,而是来自Object.toString()