Islam
Islam

Reputation: 1727

com.google.gson.internal.LinkedHashTreeMap cannot be cast to my object

I have JSON file looks like

{
    "SUBS_UID" : {
        "featureSetName" : "SIEMENSGSMTELEPHONY MULTISIM",
        "featureName" : "MULTISIMIMSI",
        "featureKey" : [{
                "key" : "SCKEY",
                "valueType" : 0,
                "value" : "0"
            }
        ]
    },
}

So the key is a String "SUBS_ID" and the value is a model called FeatureDetails which contains attributes "featureSetName,featureName,...". So i read from the JSON file using google.json lib like this,

HashMap<String, FeatureDetails> featuresFromJson = new Gson().fromJson(JSONFeatureSet, HashMap.class);

then I'm trying to loop over this HashMap getting the value and cast it to my FeatureDetails model,

for (Map.Entry entry : featuresFromJson.entrySet()) {
                    featureDetails = (FeatureDetails) entry.getValue();
                }

and here is my FeatureDetails Model,

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;
    }
} 

but i got an exception "com.google.gson.internal.LinkedHashTreeMap cannot be cast to com.asset.vsv.models.FeatureDetail".

Upvotes: 26

Views: 55159

Answers (4)

Maxim
Maxim

Reputation: 476

(objectName as Map<String, Any>).get("fieldName")

Upvotes: 2

Abhilash Das
Abhilash Das

Reputation: 1438

the code is in Kotlin: use val type = object : TypeToken<HashMap<String, FoodLogEntry>>() {}.type Gson().fromJson(dataStr, type)

instead of val type = object : TypeToken<Map<String, FoodLogEntry>>() {}.type Gson().fromJson(dataStr, type) note: HashMap instead of Map

Upvotes: 0

Алексей
Алексей

Reputation: 1847

try this:

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

and when you going through your hash map do this:

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

Upvotes: 34

Paul Richter
Paul Richter

Reputation: 11072

The reason you're seeing this is because you're telling GSON to deserialize the JSON structure using the structure of a HashMap in the line

... = new Gson().fromJson(JSONFeatureSet, HashMap.class);
                                          ^^
                                          Right here

As a result, GSON has no idea that the sub objects in the JSON are anything other than simple key-value pairs, even though the structure may match the structure of your FeatureDetails object.

One solution is to create a model which wraps your FeatureDetails object, which will act as the root of the entire structure. This object might look something like this:

public class FeatureDetailsRoot{
    private FeatureDetails SUBS_UID; // poor naming, but must match the key in your JSON
}

And finally, you'd pass that model's class:

= new Gson().fromJson(JSONFeatureSet, FeatureDetailsRoot.class)

Update

In answer to your question in the comment regarding the ability to add / have multiple FeatureDetails objects, the problem presently is that your JSON does not reflect that kind of structure. Meaning, the "SUBS_UID" key points to a single object, not an array objects. If you would like to have this ability, then your json will need to be altered so that it shows an array of objects, like this:

{
    "SUBS_UID" : [{
       "featureSetName" : "Feature set name #1",
       ...attributes for feature #1
     },
     {
       "featureSetName" : "Feature set name #2",
       ...attributes for feature #2
     },
     ...other features
     ]
}

And then you can simply alter the root class so that it contains a list of FeatureDetails objects, like so:

public class FeatureDetailsRoot{
    private List<FeatureDetails> SUBS_UID;
}

Let me know if that makes sense (or whether I've misunderstood you)

Upvotes: 6

Related Questions