java - 具有可变 Json 响应对象和 Json 属性的杰克逊泛型
问题描述
根据 VizGhar 的回答“ Jackson Generics with variable JsonProperty ”,我正在尝试使用 WebClient 来使用 API 响应,其中包含 json 响应中的通用对象:
{
"meta": {
"RID": "abc9f-defgh-hj78k-lkm9n",
"QID": "abc9f-defgh-hj78k-lkm9n" },
"data": {
"Inquiry": {
"multiCurrency": [{"TaxStat": "Y", "TaxAmt": 0}],
"Type": "Tax",
"TaxFreq": {
"weekDay": 0,
"startDay": 0
},
"TaxRegion": "Tx"
}
}
}
“查询”的类型是通用的,即“数据”是通用响应对象的包装,在这种情况下是“查询”,但它可能会改变。
查询.java:
public class Inquiry {
@JsonProperty("multiCurrency")
private List<MultiCurrencyInq> multiCurrency;
@JsonProperty("Type")
private String Type;
@JsonProperty("TaxFreq")
private TaxFreq taxFreq;
@JsonProperty("TaxRegion")
private String TaxRegion;
// Getters Setters Constructors
}
MultiCurrencyInq.java:
public class MultiCurrencyInq {
@JsonProperty("TaxStat")
private String TaxStat;
@JsonProperty("TaxAmt")
private int TaxAmt;
// Getters Setters Constructors
}
TaxFreq.java:
public class TaxFreq {
@JsonProperty("weekDay")
private int weekDay;
@JsonProperty("startDay")
private int startDay;
// Getters Setters Constructors
}
我的 Response.java 看起来像这样:
public class Response<T>{
private Meta meta;
private Data<T> data;
// Getters Setters Constructors
}
元.java:
public class Meta{
private String RID;
private String QID;
// Getters Setters Constructors
}
数据.java:
public class Data<T> {
// property name, that will be changed
@JsonProperty(DataNamingStrategy.DATA_FIELD)
private T data;
// Getters Setters Constructors
}
我的控制器:
@RestController
public class InquiryController {
@Autowired private WebClient webClient;
@GetMapping("/inquiry") public Response<Inquiry> getInquiryApiResponse() {
ResponseEntity<String> response = webClient.get()
.uri("http://my.org.com/clientId/inquiry")
.retrieve()
.toEntity(String.class)
.block();
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new DataNamingStrategy("Inquiry"));
JavaType type = mapper.getTypeFactory()
.constructParametricType(Response.class, Inquiry.class);
Response<Inquiry> res = mapper.readValue(response.getBody(), type);
return res;
}
}
数据命名策略.java:
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);
}
}
这对我不起作用。在 Data.java 中未将@JsonProperty(DataNamingStrategy.DATA_FIELD)的泛型类型设置为“查询”的原因可能是什么
解决方案
在 Data.java 中未将 @JsonProperty(DataNamingStrategy.DATA_FIELD) 的泛型类型设置为“查询”的原因可能是什么
原因是默认情况下JsonProperty
带注释的属性名称不能由DataNamingStrategy
. Jackson 具有默认禁用的此功能。
ALLOW_EXPLICIT_PROPERTY_RENAMING 启用后将允许显式命名的属性(即,使用 JsonProperty("explicitName") 注释的字段或方法)由 PropertyNamingStrategy 重命名(如果已配置)的功能。默认情况下禁用该功能。
自:2.7
您需要做的就是启用此功能 -
ObjectMapper mapper = new ObjectMapper();
mapper.enable(MapperFeature.ALLOW_EXPLICIT_PROPERTY_RENAMING);
这是相关的杰克逊笔记历史(参考这里)
Prior versions allowed explicit property renaming by default
v2.4 - Jackson stopped allowing property renaming. (#428)
v2.7 - Introduced ALLOW_EXPLICIT_PROPERTY_RENAMING feature to allow / disallow Explicit Property renaming (#918)
推荐阅读
- html - 即使没有添加不透明度,画布和边框也显示透明
- java - 跟踪 Spark 结构化流中的消费消息
- css - Angular:使用 fxflex 将垫子工具提示与左对齐
- django - 通过文件名获取 ImageField 中文件的实例
- html - background-size: 100% 100% 上传后不起作用
- python - 使用 CV2 对视频进行镜像/对称效果
- python - BeautifulSoup - 不能按标点符号过滤列表结果
- numpy - np.dot 给出关于形状的值错误
- python - 使用 sympy 象征性地获得分数的实部
- javascript - 升级 vuejs 应用程序时如何解决此错误?