带有变量 JsonProperty 的 Jackson 泛型(与泛型一起使用) [英] Jackson Generics with variable JsonProperty (usage with generics)
问题描述
我有这样的课程:
public class Data<U> {
@JsonProperty("difficulties")
private U[] data;
// ... geter setter constructor
}
而且我不想再创建 10 个类似的类,因为我只需要更改一行代码(在这种情况下为 @JsonProperty("difficulties")).属性值取决于类型.可以在一个班级里写吗?
And I don't want to create 10 more similar classes just because I need to change only one line of code (@JsonProperty("difficulties") in this case). The property value depends on Type. Is it possible to write it in one class?
推荐答案
基于 Jackson - 在没有注释的情况下在运行时修改属性 作者 Michał Ziober 在这里我能够更改默认字段名称值通过覆盖 PropertyNamingStrategy:
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:
这些是我收到的 JSON 示例(简化版):
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).
基于JSON响应的响应类:
Response class based on JSON response:
public class Response<T>{
private String status;
private String error;
private Data<T> data;
// Getters Setters Constructors
}
基于JSON响应的数据类:
Data class based on JSON response:
public class Data<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
public class DataNamingStrategy extends PropertyNamingStrategy{
// used by other classes (this will be default field name that should be changed)
public static final String DATA_FIELD = "variable:data";
private String fieldName;
public DataNamingStrategy(String fieldName) {
this.fieldName = fieldName;
}
// use this to change field name (format "variable":"value") not needed in my case
@Override
public String nameForField(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":{})
@Override
public String nameForSetterMethod(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
@Override
public String nameForGetterMethod(MapperConfig<?> config,
AnnotatedMethod method, String defaultName) {
return nameForSetterMethod(config, method, defaultName);
}
}
用法应该是这样的:
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new DataNamingStrategy(tableName));
JavaType type = mapper.getTypeFactory().constructParametricType(Response.class, dataClass);
Response<U> u = mapper.readValue(result, type);
其中 result
是 Json as String,tableName
是将在 JSON 中使用的字符串而不是默认值,dataClass
是 dataClass
的类code>U(例如 Difficulty.class).
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).
PropertyNamingStrategy
的更好用法应该是 Map
而不是一个 String
.但我只需要更改一个特定值.
Better usage of PropertyNamingStrategy
should be Map
instead of one String
. But I just needed to change one particular value.
也看看PropertyNamingStrategy
文档 或再次访问 Michał Ziober 的回答
这篇关于带有变量 JsonProperty 的 Jackson 泛型(与泛型一起使用)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!