com.google.gson.internal.LinkedHashTreeMap无法强制转换为我的对象

Isl*_*lam 21 java json gson

我有JSON文件的样子

{
    "SUBS_UID" : {
        "featureSetName" : "SIEMENSGSMTELEPHONY MULTISIM",
        "featureName" : "MULTISIMIMSI",
        "featureKey" : [{
                "key" : "SCKEY",
                "valueType" : 0,
                "value" : "0"
            }
        ]
    },
}
Run Code Online (Sandbox Code Playgroud)

所以键是一个字符串"SUBS_ID",该值是一个名为FeatureDetails的模型,它包含属性"featureSetName,featureName,...".所以我像这样使用google.json lib从JSON文件中读取,

HashMap<String, FeatureDetails> featuresFromJson = new Gson().fromJson(JSONFeatureSet, HashMap.class);
Run Code Online (Sandbox Code Playgroud)

然后我试图循环这个HashMap获取值并将其转换为我的FeatureDetails模型,

for (Map.Entry entry : featuresFromJson.entrySet()) {
                    featureDetails = (FeatureDetails) entry.getValue();
                }
Run Code Online (Sandbox Code Playgroud)

这是我的FeatureDetails模型,

public class FeatureDetails {

    private String featureSetName;
    private String featureName;
    private ArrayList<FeatureKey> featureKey;
    private String groupKey;
    private String groupValue;

    public FeatureDetails() {
        featureKey =  new ArrayList<FeatureKey>();
    }

    public ArrayList<FeatureKey> getFeatureKey() {
        return featureKey;
    }

    public void setFeatureKey(ArrayList<FeatureKey> featureKey) {
        this.featureKey = featureKey;
    }

    public String getGroupKey() {
        return groupKey;
    }

    public void setGroupKey(String groupKey) {
        this.groupKey = groupKey;
    }

    public String getGroupValue() {
        return groupValue;
    }

    public void setGroupValue(String groupValue) {
        this.groupValue = groupValue;
    }

    public String getFeatureName() {
        return featureName;
    }

    public void setFeatureName(String featureName) {
        this.featureName = featureName;
    }

    public String getFeatureSetName() {
        return featureSetName;
    }

    public void setFeatureSetName(String featureSetName) {
        this.featureSetName = featureSetName;
    }
} 
Run Code Online (Sandbox Code Playgroud)

但我得到一个例外"com.google.gson.internal.LinkedHashTreeMap无法转换为com.asset.vsv.models.FeatureDetail".

Але*_*сей 33

试试这个:

HashMap<String, FeatureDetails> featuresFromJson = new Gson().fromJson(JSONFeatureSet, new TypeToken<Map<String, FeatureDetails>>() {}.getType());
Run Code Online (Sandbox Code Playgroud)

当你浏览你的哈希映射时,执行以下操作:

for (Map.Entry<String, FeatureDetails> entry : featuresFromJson.entrySet()) {
                    FeatureDetails featureDetails = entry.getValue();
}
Run Code Online (Sandbox Code Playgroud)

  • 我看到(lol)然后`new TypeToken <HashMap <String,FeatureDetails>(){}.getType()`会做 (7认同)
  • 一些背景:LinkedHashTreeMap是Gson中存在的一个类,用于防御哈希冲突DoS攻击.它在常见情况下像HashMap一样执行,在最坏的情况下像TreeMap一样.http://arstechnica.com/business/2011/12/huge-portions-of-web-vulnerable-to-hashing-denial-of-service-attack/ (6认同)
  • 一个`HashMap`实现`Map`接口,我loled的原因是,谷歌是不同的:)所以在这种情况下,当您从`Json`到`Object`使用`TypeToken`具体说明它是`地图转换`,`fromGson`返回`com.google.gson.internal.LinkedHashTreeMap`,它不能分配给`HashMap`.所以这样做的正确方法是`地图<字符串,FeatureDetails> featuresFromJson =新GSON()fromJson(STR,新TypeToken <地图<字符串,FeatureDetails >>(){} .getType());` (3认同)

Pau*_*ter 5

你看到这种情况的原因是因为你告诉GSON使用的结构反序列化JSON的结构HashMap在线路

... = new Gson().fromJson(JSONFeatureSet, HashMap.class);
                                          ^^
                                          Right here
Run Code Online (Sandbox Code Playgroud)

因此,即使结构可能与FeatureDetails对象的结构匹配,GSON也不知道JSON中的子对象是除简单键值对之外的任何东西.

一种解决方案是创建一个包装FeatureDetails对象的模型,该模型将充当整个结构的根.此对象可能如下所示:

public class FeatureDetailsRoot{
    private FeatureDetails SUBS_UID; // poor naming, but must match the key in your JSON
}
Run Code Online (Sandbox Code Playgroud)

最后,你将通过该模型的课程:

= new Gson().fromJson(JSONFeatureSet, FeatureDetailsRoot.class)
Run Code Online (Sandbox Code Playgroud)

更新

在关于添加/拥有多个FeatureDetails对象的能力的评论中回答你的问题,目前的问题是你的JSON没有反映出那种结构.意思是,"SUBS_UID"关键点指向单个对象,而不是数组对象.如果你想拥有这种能力,那么你的json需要被改变,以便它显示一个对象数组,如下所示:

{
    "SUBS_UID" : [{
       "featureSetName" : "Feature set name #1",
       ...attributes for feature #1
     },
     {
       "featureSetName" : "Feature set name #2",
       ...attributes for feature #2
     },
     ...other features
     ]
}
Run Code Online (Sandbox Code Playgroud)

然后你可以简单地改变根类,使它包含一个FeatureDetails对象列表,如下所示:

public class FeatureDetailsRoot{
    private List<FeatureDetails> SUBS_UID;
}
Run Code Online (Sandbox Code Playgroud)

让我知道这是否有意义(或者我是否误解了你)