Jackson Generics With Variable Jsonproperty (usage With Generics)
Solution 1:
Based on response of Jackson - Modify an attribute at runtime without annotation by Michał Ziober here I was able to change default field name values by overriding PropertyNamingStrategy:
These are my received JSON examples (simplified):
{"status":"OK","error":null,"data":{"difficulties":[{"value":"easy"},{"value":"medium"}]}}{"status":"ok","error":null,"data":{"countries":[{"code":"AT"},{"code":"BE"}]}}
see the difference in second line where data object contains either difficulties or countries (or many other names based on context).
Response class based on JSON response:
publicclassResponse<T>{
privateString status;
privateStringerror;
private Data<T> data;
// Getters Setters Constructors
}
Data class based on JSON response:
publicclassData<T> {
// property name, that will be changed@JsonProperty(DataNamingStrategy.DATA_FIELD)private T[] data;
// Getters Setters Constructors
}
And this is Naming strategy, that changes default value to runtime specified value
publicclassDataNamingStrategyextendsPropertyNamingStrategy{
// used by other classes (this will be default field name that should be changed)publicstatic final StringDATA_FIELD = "variable:data";
privateString fieldName;
publicDataNamingStrategy(String fieldName) {
this.fieldName = fieldName;
}
// use this to change field name (format "variable":"value") not needed in my case@OverridepublicStringnameForField(MapperConfig<?> config, AnnotatedField field,
String defaultName) {
return (defaultName.equals(DATA_FIELD))?
fieldName :
super.nameForField(config, field, defaultName);
}
// use this to change setter method field name (JSON -> Object with format "variable":{})@OverridepublicStringnameForSetterMethod(MapperConfig<?> config,
AnnotatedMethod method, String defaultName) {
return (defaultName.equals(DATA_FIELD))?
fieldName :
super.nameForGetterMethod(config, method, defaultName);
}
// use this to change getter method field name (Object -> JSON with format "variable":{})// should be same as nameForSetterMethod@OverridepublicStringnameForGetterMethod(MapperConfig<?> config,
AnnotatedMethod method, String defaultName) {
returnnameForSetterMethod(config, method, defaultName);
}
}
And usage should look like this:
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new DataNamingStrategy(tableName));
JavaType type = mapper.getTypeFactory().constructParametricType(Response.class, dataClass);
Response<U> u = mapper.readValue(result, type);
Where result
is Json as String, tableName
is String that will be used in JSON instead of default value and dataClass
is class for U
(for example Difficulty.class).
Better usage of PropertyNamingStrategy
should be Map
instead of one String
. But I just needed to change one particular value.
Also have a look at PropertyNamingStrategy
documentation or again at Michał Ziober's answer
Solution 2:
You can use @JsonAnyGetter
annotation.
publicclassData<U> {
@JsonIgnoreprivate U[] data;
@JsonIgnoreprivateString propertyName;
publicData(String propertyName) {
this.propertyName = propertyName;
}
// ... geter setter@JsonAnyGetterpublicMap<String, Object> any() {
returnCollections.singletonMap(propertyName, data);
}
}
And use it like below:
Data<Difficulties> difficulties = new Data<>("difficulties");
write whatever you want instead of "difficulties" string. Set your list to Data generic class instead of Difficulties object if you want
Post a Comment for "Jackson Generics With Variable Jsonproperty (usage With Generics)"