具有变量Json响应对象和Json属性的java Jackson泛型
基于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"
}
}
}
其中,“查询”的类型是泛型的,即“数据”是泛型响应对象的包装,在本例中为“查询”,但它可能会更改
调查。爪哇:
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
}
多币种。爪哇:
public class MultiCurrencyInq {
@JsonProperty("TaxStat")
private String TaxStat;
@JsonProperty("TaxAmt")
private int TaxAmt;
// Getters Setters Constructors
}
TaxFreq。爪哇:
public class TaxFreq {
@JsonProperty("weekDay")
private int weekDay;
@JsonProperty("startDay")
private int startDay;
// Getters Setters Constructors
}
我的回答。java看起来像这样:
public class Response<T>{
private Meta meta;
private Data<T> data;
// Getters Setters Constructors
}
梅塔。爪哇:
public class Meta{
private String RID;
private String QID;
// Getters Setters Constructors
}
数据。爪哇:
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;
}
}
数据命名策略。爪哇:
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);
}
}
这对我不起作用。对于数据中的@JsonProperty(DataNamingStrategy.DATA_字段),不将泛型类型设置为“查询”的原因可能是什么。爪哇
# 1 楼答案
原因是默认情况下
JsonProperty
注释的属性名不能被DataNamingStrategy
重命名。Jackson有默认禁用的this功能您只需启用此功能-
以下是相关的Jackson notes历史记录(参考here)
# 2 楼答案
您可以直接使用WebClient和ParameterizedTypeReference类进行反序列化。以下是您的工作示例:
以下代码的响应(查询和dummeyentity):
查询
多币种
TaxFreq
虚拟实体
第三方客户端(WebClient Impl)
第三方响应
Json虚拟实体
测试
项目结构
Pom
上面的相同示例适用于Jackson,但使用TypeReference类代替ParameterizedTypeReference,但为了优化,最好使用相同的WebClient执行反序列化