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".
Some background: LinkedHashTreeMap is a class that exists in Gson to defend against hash-collision DoS attacks. It performs like HashMap in the common case and like TreeMap in the worst case. arstechnica.com/business/2011/12/…
You can iterate through the ArrayList to convert each LinkedTreeMap item to a Product item. You can use Gson a second time to do the conversion. See example code here: randomgyan.com/… In my opinion, due to type erasure, the parser can't fetch the real type T at runtime. One workaround would be to provide the class type as parameter to the method.
The keep statements should go all the way down to just the specific class you need, rather than keeping all of com.google.** and sun.misc.**. The correct rule is something like "-keep class com.google.api.services.vision.v1.model.BatchAnnotateImagesResponse { <fields>; }", depending where the GSON model class you are using is stored.
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.
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(); }
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With