I try to write a custom JsonDeserializer, but I can't figure out how to get the Generic type information of my class.
I18NProperty.class:
public class I18NProperty<T> extends ArrayList<T> {
public static class Content<T> {
public Locale i18n;
public T val;
}
}
My desired JSON representation looks like this ( name
is an instance of I18NProperty<Content<String>>
) :
{
"name": {
"en": "foo",
"jp": "bar"
}
}
Now I tried to write a JsonDeserializer
and I'm able to read the field names and values, but I can't figure out how to create an instance of the generic type (in this example String
):
public static class I18NPropertyDeserializer extends StdDeserializer<I18NProperty<? extends Content<?>>> {
protected I18NPropertyDeserializer() {
super(I18NProperty.class);
}
@Override
public I18NProperty<? extends Content<?>> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
I18NProperty<Content<?>> result = new I18NProperty<>();
while(p.nextToken() != JsonToken.END_OBJECT) {
String lang = p.getCurrentName();
p.nextToken();
--> Object val = p.readValueAs(Object.class);
--> I18NProperty.Content<?> c = new I18NProperty.Content<>();
c.i18n = new Locale(lang);
--> c.val = null;
result.add(c);
}
return result;
}
}
I marked the lines with -->
where I need the Generic Type information.
This must be possible somehow, because normally I can give Jackson a arbitrary class which contains any generic fields and it will correctly deserialize it.
Thanks in advance, Benjamin
your code probably won't work because
public static class I18NPropertyDeserializer extends StdDeserializer<I18NProperty<? extends Content<?>>>
affirm that the private variable of Content public T val;
is also Content because I18NProperty<T>
and public T val
means that what ever goes between <> of I18NProperty is going to be the type of val, and you don't want to have val of type Content right!! you want it to be a simple object like String, Integer, Float ...
public class I18NProperty<T> extends ArrayList<T>
means that I18NProperty is going to extend ArrayList<String>
in case val is String ArrayList<Integer>
in case val is Integer ... you get it what i mean .But what you want is that I18NProperty extends Array<Content<T>>
So i made a change in the class I18NProperty<T>
to make it extends ArrayList<Content>
.
For the class I18NPropertyDeserialize what i have done is i made the class generic to have information about type T of public T val;
and in order to instantiate the class of type T we should have object class for that type passed to the constructor I18NPropertyDeserializer(Class<T> clazz)
now we are able to instantiate the object wich is going to be put in Content.val
I18NPropertyDeserialize :
public class I18NPropertyDeserializer<T> extends
StdDeserializer<I18NProperty<T>> {
private Class<T> clazz;
protected I18NPropertyDeserializer(Class<T> clazz) {
super(I18NProperty.class);
this.clazz = clazz;
}
@Override
public I18NProperty<T> deserialize(JsonParser p,
DeserializationContext ctxt) throws IOException,
JsonProcessingException {
I18NProperty<T> result = new I18NProperty<>();
while (p.nextToken() != JsonToken.END_OBJECT) {
String lang = p.getCurrentName();
p.nextToken();
T val;
val = p.readValueAs(clazz);
I18NProperty.Content<T> c = new I18NProperty.Content<>();
c.i18n = new Locale(lang);
c.val = val;
result.add(c);
}
return result;
}
}
I18NProperty
public class I18NProperty<T> extends ArrayList<I18NProperty.Content<T>> {
public static class Content<T> {
public Locale i18n;
public T val;
}}
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