I have the JSON below:
{
"abc": {
"linkedTo": "count",
// possibly more data...
},
"plmtq": {
"linkedTo": "title",
"decode": "true",
// possibly more data...
}
}
I need to load this JSON into a Map<String, Holder>
, with keys "abc"
and "plmtq"
.
Below is my Holder
class:
public class Holder {
private final Map<String, String> data;
public Holder(Map<String, String> data) {
this.data = data;
}
// More methods in this class...
}
The JSON does not match my class structure, but I cannot change the JSON or the classes.
What I need is a way to customize the deserialization so I can parse the JSON into a Map<String, Holder>
.
Is there any way to do this?
Below is the code which does that, but it looks too complex and there must be a simpler way to do it...
private static Map<String, Holder> getMap(String jsonLine)
{
Map<String, Holder> holder = new HashMap<>();
JsonElement jelement = new JsonParser().parse(jsonLine);
JsonObject jobject = jelement.getAsJsonObject();
for (Map.Entry<String, JsonElement> entry : jobject.entrySet())
{
Map<String, String> metadata = new HashMap<>();
JsonObject element = entry.getValue().getAsJsonObject();
for (Map.Entry<String, JsonElement> entry2 : element.entrySet())
{
metadata.put(entry2.getKey(), entry2.getValue().getAsString());
}
holder.put(entry.getKey(), new Holder(metadata));
}
return holder;
}
If you really need to keep your
Holder
class as is, the only option I can think of is to create a custom deserializer for yourHolder
class.By doing this, whenever you tell Gson to parse some JSON into a
Holder
object, it will use your deserializer, instead of doing it 'the normal way' (i.e., mapping JSON keys to object properties).Something like this:
Then you register your deserializer when creating the
Gson
object:And finally, you parse your JSON like this:
You may want to look at Gson's docs for custom (de)serialization and this other answer of mine to get more info...
Note: this answer has been edited to make it clearer after discussion in comments/chat.