Reputation: 11669
I have a custom deserializer for my class as shown below:
private class HolderDeserializer implements JsonDeserializer<Holder> {
@Override
public Holder deserialize(JsonElement json, Type type, JsonDeserializationContext context)
throws JsonParseException {
Type mapType = new TypeToken<Map<String, String>>() {}.getType();
// in the below data map, I want value to be stored in lowercase
// how can I do that?
Map<String, String> data = context.deserialize(json, mapType);
return new Holder(data);
}
}
And this is how I register my deserializer when creating the Gson object:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Holder.class, new HolderDeserializer());
Gson gson = gsonBuilder.create();
And finally, parsing my JSON like this:
Type responseType = new TypeToken<Map<String, Holder>>() {}.getType();
Map<String, Holder> response = gson.fromJson(jsonLine, responseType);
In my deserialize
method, value of json
is coming as like this {"linkedTo":"COUNT"}
and then it get loaded into data map as {linkedTo=COUNT}
. I wanted to see if there is any way by which all the value of data
map can be lowercase so instead of this {linkedTo=COUNT}
, it should get stored like this {linkedTo=count}
in data map automatically?
Is there any way to do this in Gson itself automatically?
Update:
Below is my JSON content:
{
"abc": {
"linkedTo": "COUNT",
// possibly more data...
},
"plmtq": {
"linkedTo": "TITLE",
"decode": "TRUE",
// possibly more data...
}
}
Upvotes: 1
Views: 2515
Reputation: 15533
Firstly, it is suggested to use Gson TypeAdapter instead of JsonDeserializer. So I'm going to answer your question with it:
New applications should prefer TypeAdapter, whose streaming API is more efficient than this interface's tree API.
Question: How can we modify the json content before deserialization ?
One of the solutions: Preprocess the json content before deserialization and modify some of its contents.
How can we achive this with TypeAdapter: Define a custom TypeAdapter
, get the json content at its read
method (which is called just before the deserialization) and modify the content.
Code sample:
Define a TypeAdapterFactory
and a TypeAdapter
;
TypeAdapterFactory myCustomTypeAdapterFactory = new TypeAdapterFactory() {
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type); //
return new TypeAdapter<T>() {
public void write(JsonWriter out, T value) throws IOException {
JsonElement tree = delegate.toJsonTree(value);
beforeWrite(value, tree);
elementAdapter.write(out, tree);
}
public T read(JsonReader in) throws IOException {
JsonElement tree = elementAdapter.read(in);
afterRead(tree);
return delegate.fromJsonTree(tree);
}
/**
* Modify {@code toSerialize} before it is written to
* the outgoing JSON stream.
*/
protected void beforeWrite(T source, JsonElement toSerialize) {
}
/**
* Modify {@code deserialized} before it is parsed
*/
protected void afterRead(JsonElement deserialized) {
if(deserialized instanceof JsonObject) {
JsonObject jsonObject = ((JsonObject)deserialized);
Set<Map.Entry<String, JsonElement>> entrySet = jsonObject.entrySet();
for(Map.Entry<String,JsonElement> entry : entrySet){
if(entry.getValue() instanceof JsonPrimitive) {
if(entry.getKey().equalsIgnoreCase("linkedTo")) {
String val = jsonObject.get(entry.getKey()).toString();
jsonObject.addProperty(entry.getKey(), val.toLowerCase());
}
} else {
afterRead(entry.getValue());
}
}
}
}
};
}
};
We've added an extra process before deserialization. We get the entrySet
from json content and updated linkedTo
key's value.
Working sample:
String jsonContent = "{\"abc\":{\"linkedTo\":\"COUNT\"},\"plmtq\":{\"linkedTo\":\"TITLE\",\"decode\":\"TRUE\"}}";
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapterFactory(myCustomTypeAdapterFactory);
Gson gson = gsonBuilder.create();
Map mapDeserialized = gson.fromJson(jsonContent, Map.class);
Output:
This is the similar answer for your question.
Upvotes: 3