具有变量 Json 响应对象和 Json 属性 的 Jackson 泛型
Jackson Generics with variable Json response object and Json property
根据 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"
}
}
}
其中“查询”的类型是通用的,即“数据”是通用响应对象的包装器,在这种情况下是 'Inquiry',但它可能会改变。
Inquiry.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
}
Meta.java:
public class Meta{
private String RID;
private String QID;
// Getters Setters Constructors
}
Data.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;
}
}
DataNamingStrategy.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);
}
}
这对我不起作用。没有将通用类型设置为 "Inquiry" for @JsonProperty(DataNamingStrategy.DATA_FIELD) in Data.java 的原因可能是什么? ]
您可以直接使用 WebClient 和 ParameterizedTypeReference class 进行反序列化。以下是您的工作示例:
以下代码的响应(查询和 DummyEntity):
// Inquiry Entity
ThirdPartyAPIResponse(meta=ThirdPartyAPIResponse.Meta(rid=abc9f-defgh-hj78k-lkm9n, qid=abc9f-defgh-hj78k-lkm9n), data=ThirdPartyAPIResponse.Data(data=Inquiry(multiCurrency=[MultiCurrencyInq(taxStat=Y, taxAmt=1)], type=Tax, taxFreq=TaxFreq(weekDay=1, startDay=1), taxRegion=Tx)))
// Dummy Entity
ThirdPartyAPIResponse(meta=ThirdPartyAPIResponse.Meta(rid=abc9f-defgh-hj78k-lkm9n, qid=abc9f-defgh-hj78k-lkm9n), data=ThirdPartyAPIResponse.Data(data=DummyEntity(code=200, message=Hello World)))
询价
package com.Whosebug.q69665171.entities;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter @Setter @ToString
public class Inquiry {
@JsonProperty("multiCurrency") private List<MultiCurrencyInq> multiCurrency;
@JsonProperty("Type") private String type;
@JsonProperty("TaxFreq") private TaxFreq taxFreq;
@JsonProperty("TaxRegion") private String taxRegion;
}
MultiCurrencyInq
package com.Whosebug.q69665171.entities;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter @Setter @ToString
public class MultiCurrencyInq {
@JsonProperty("TaxStat") private String taxStat;
@JsonProperty("TaxAmt") private Integer taxAmt;
}
税收频率
package com.Whosebug.q69665171.entities;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter @Setter @ToString
public class TaxFreq {
@JsonProperty("weekDay") private Integer weekDay;
@JsonProperty("startDay") private Integer startDay;
}
虚拟实体
package com.Whosebug.q69665171.entities;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter @Setter @ToString
public class DummyEntity {
@JsonProperty("code") private Integer code;
@JsonProperty("message") private String message;
}
ThirdPartyAPIClient(WebClient 实现)
package com.Whosebug.q69665171.third_party;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import com.Whosebug.q69665171.entities.Inquiry;
@Component
public class ThirdPartyAPIClient {
private WebClient webClient;
public ThirdPartyAPIClient() {
webClient = WebClient.create();
}
// The port is for testing scopes only, as the mock web server
// defines a random one
public ThirdPartyAPIResponse<Inquiry> getInquiryApiResponse(int port) {
return webClient.get()
.uri("http://localhost:" + port + "/test")
.retrieve()
.bodyToMono(
new ParameterizedTypeReference<ThirdPartyAPIResponse<Inquiry>>(){}
).block();
}
public ThirdPartyAPIResponse<DummyEntity> getDummyEntityApiResponse(int port) {
return webClient.get()
.uri("http://localhost:" + port + "/test2")
.retrieve()
.bodyToMono(
new ParameterizedTypeReference<ThirdPartyAPIResponse<DummyEntity>>(){}
).block();
}
}
ThirdPartyAPIResponse
package com.Whosebug.q69665171.third_party;
import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter @Setter @ToString
public class ThirdPartyAPIResponse <T> {
@JsonProperty("meta") private Meta meta;
@JsonProperty("data") private Data <T> data;
@Getter @Setter @ToString
public static class Meta {
@JsonProperty("RID") private String rid;
@JsonProperty("QID") private String qid;
}
@Getter @Setter @ToString
public static class Data <T> {
@JsonAlias({"Inquiry","DummyEntity"}) private T data;
}
}
Json 虚拟实体
{
"meta":{
"RID":"abc9f-defgh-hj78k-lkm9n",
"QID":"abc9f-defgh-hj78k-lkm9n"
},
"data":{
"DummyEntity":{
"code": 200,
"message": "Hello World"
}
}
}
测试
package com.Whosebug.q69665171;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import com.Whosebug.q69665171.third_party.ThirdPartyAPIClient;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
@SpringBootTest
class ApplicationTests {
private static MockWebServer webServer;
@Autowired private ThirdPartyAPIClient client;
@BeforeAll
static void setUp() throws IOException {
webServer = new MockWebServer();
webServer.start();
}
@AfterAll
static void tearDown() throws IOException {
webServer.shutdown();
}
@Test
void should_Retrieve_Inquiry_Response_When_Consumes_Inquiry_API() throws Exception {
final String thirdPartyResponse = readJsonTestResource("response.json");
//System.out.println(thirdPartyResponse);
// Mock
webServer.enqueue(new MockResponse().setResponseCode(200)
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.setBody(thirdPartyResponse)
);
System.out.println(client.getInquiryApiResponse(webServer.getPort()));
assertEquals(0, 0);
}
private String readJsonTestResource(String fileName) throws Exception {
File resource = new ClassPathResource(fileName).getFile();
return new String(Files.readAllBytes(resource.toPath()));
}
@Test
void should_Retrieve_Dummy_Entity_Response_When_Consumes_Dummy_API() throws Exception {
final String thirdPartyResponse = readJsonTestResource("response2.json");
//System.out.println(thirdPartyResponse);
// Mock
webServer.enqueue(new MockResponse().setResponseCode(200)
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.setBody(thirdPartyResponse)
);
System.out.println(client.getDummyEntityApiResponse(webServer.getPort()));
assertEquals(0, 0);
}
}
项目结构
Pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.Whosebug.q69665171</groupId>
<artifactId>69665171</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>69665171</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
上面的相同示例适用于 Jackson,但使用的是 TypeReference class 而不是 ParameterizedTypeReference,但为了优化,最好使用相同的 WebClient 执行反序列化。
What could be the reason for not setting the generic type to "Inquiry"
for @JsonProperty(DataNamingStrategy.DATA_FIELD) in Data.java
原因是默认情况下JsonProperty
注解的属性名称不能被DataNamingStrategy
重命名。 Jackson 具有默认禁用的 this 功能。
ALLOW_EXPLICIT_PROPERTY_RENAMING Feature that when enabled will allow
explicitly named properties (i.e., fields or methods annotated with
JsonProperty("explicitName")) to be re-named by a
PropertyNamingStrategy, if one is configured. Feature is disabled by
default.
Since:
2.7
您需要做的就是启用此功能 -
ObjectMapper mapper = new ObjectMapper();
mapper.enable(MapperFeature.ALLOW_EXPLICIT_PROPERTY_RENAMING);
这里是相关的杰克逊笔记历史(参考自here)
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)
根据 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"
}
}
}
其中“查询”的类型是通用的,即“数据”是通用响应对象的包装器,在这种情况下是 'Inquiry',但它可能会改变。
Inquiry.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
}
Meta.java:
public class Meta{
private String RID;
private String QID;
// Getters Setters Constructors
}
Data.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;
}
}
DataNamingStrategy.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);
}
}
这对我不起作用。没有将通用类型设置为 "Inquiry" for @JsonProperty(DataNamingStrategy.DATA_FIELD) in Data.java 的原因可能是什么? ]
您可以直接使用 WebClient 和 ParameterizedTypeReference class 进行反序列化。以下是您的工作示例:
以下代码的响应(查询和 DummyEntity):
// Inquiry Entity
ThirdPartyAPIResponse(meta=ThirdPartyAPIResponse.Meta(rid=abc9f-defgh-hj78k-lkm9n, qid=abc9f-defgh-hj78k-lkm9n), data=ThirdPartyAPIResponse.Data(data=Inquiry(multiCurrency=[MultiCurrencyInq(taxStat=Y, taxAmt=1)], type=Tax, taxFreq=TaxFreq(weekDay=1, startDay=1), taxRegion=Tx)))
// Dummy Entity
ThirdPartyAPIResponse(meta=ThirdPartyAPIResponse.Meta(rid=abc9f-defgh-hj78k-lkm9n, qid=abc9f-defgh-hj78k-lkm9n), data=ThirdPartyAPIResponse.Data(data=DummyEntity(code=200, message=Hello World)))
询价
package com.Whosebug.q69665171.entities;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter @Setter @ToString
public class Inquiry {
@JsonProperty("multiCurrency") private List<MultiCurrencyInq> multiCurrency;
@JsonProperty("Type") private String type;
@JsonProperty("TaxFreq") private TaxFreq taxFreq;
@JsonProperty("TaxRegion") private String taxRegion;
}
MultiCurrencyInq
package com.Whosebug.q69665171.entities;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter @Setter @ToString
public class MultiCurrencyInq {
@JsonProperty("TaxStat") private String taxStat;
@JsonProperty("TaxAmt") private Integer taxAmt;
}
税收频率
package com.Whosebug.q69665171.entities;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter @Setter @ToString
public class TaxFreq {
@JsonProperty("weekDay") private Integer weekDay;
@JsonProperty("startDay") private Integer startDay;
}
虚拟实体
package com.Whosebug.q69665171.entities;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter @Setter @ToString
public class DummyEntity {
@JsonProperty("code") private Integer code;
@JsonProperty("message") private String message;
}
ThirdPartyAPIClient(WebClient 实现)
package com.Whosebug.q69665171.third_party;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import com.Whosebug.q69665171.entities.Inquiry;
@Component
public class ThirdPartyAPIClient {
private WebClient webClient;
public ThirdPartyAPIClient() {
webClient = WebClient.create();
}
// The port is for testing scopes only, as the mock web server
// defines a random one
public ThirdPartyAPIResponse<Inquiry> getInquiryApiResponse(int port) {
return webClient.get()
.uri("http://localhost:" + port + "/test")
.retrieve()
.bodyToMono(
new ParameterizedTypeReference<ThirdPartyAPIResponse<Inquiry>>(){}
).block();
}
public ThirdPartyAPIResponse<DummyEntity> getDummyEntityApiResponse(int port) {
return webClient.get()
.uri("http://localhost:" + port + "/test2")
.retrieve()
.bodyToMono(
new ParameterizedTypeReference<ThirdPartyAPIResponse<DummyEntity>>(){}
).block();
}
}
ThirdPartyAPIResponse
package com.Whosebug.q69665171.third_party;
import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter @Setter @ToString
public class ThirdPartyAPIResponse <T> {
@JsonProperty("meta") private Meta meta;
@JsonProperty("data") private Data <T> data;
@Getter @Setter @ToString
public static class Meta {
@JsonProperty("RID") private String rid;
@JsonProperty("QID") private String qid;
}
@Getter @Setter @ToString
public static class Data <T> {
@JsonAlias({"Inquiry","DummyEntity"}) private T data;
}
}
Json 虚拟实体
{
"meta":{
"RID":"abc9f-defgh-hj78k-lkm9n",
"QID":"abc9f-defgh-hj78k-lkm9n"
},
"data":{
"DummyEntity":{
"code": 200,
"message": "Hello World"
}
}
}
测试
package com.Whosebug.q69665171;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import com.Whosebug.q69665171.third_party.ThirdPartyAPIClient;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
@SpringBootTest
class ApplicationTests {
private static MockWebServer webServer;
@Autowired private ThirdPartyAPIClient client;
@BeforeAll
static void setUp() throws IOException {
webServer = new MockWebServer();
webServer.start();
}
@AfterAll
static void tearDown() throws IOException {
webServer.shutdown();
}
@Test
void should_Retrieve_Inquiry_Response_When_Consumes_Inquiry_API() throws Exception {
final String thirdPartyResponse = readJsonTestResource("response.json");
//System.out.println(thirdPartyResponse);
// Mock
webServer.enqueue(new MockResponse().setResponseCode(200)
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.setBody(thirdPartyResponse)
);
System.out.println(client.getInquiryApiResponse(webServer.getPort()));
assertEquals(0, 0);
}
private String readJsonTestResource(String fileName) throws Exception {
File resource = new ClassPathResource(fileName).getFile();
return new String(Files.readAllBytes(resource.toPath()));
}
@Test
void should_Retrieve_Dummy_Entity_Response_When_Consumes_Dummy_API() throws Exception {
final String thirdPartyResponse = readJsonTestResource("response2.json");
//System.out.println(thirdPartyResponse);
// Mock
webServer.enqueue(new MockResponse().setResponseCode(200)
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.setBody(thirdPartyResponse)
);
System.out.println(client.getDummyEntityApiResponse(webServer.getPort()));
assertEquals(0, 0);
}
}
项目结构
Pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.Whosebug.q69665171</groupId>
<artifactId>69665171</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>69665171</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
上面的相同示例适用于 Jackson,但使用的是 TypeReference class 而不是 ParameterizedTypeReference,但为了优化,最好使用相同的 WebClient 执行反序列化。
What could be the reason for not setting the generic type to "Inquiry" for @JsonProperty(DataNamingStrategy.DATA_FIELD) in Data.java
原因是默认情况下JsonProperty
注解的属性名称不能被DataNamingStrategy
重命名。 Jackson 具有默认禁用的 this 功能。
ALLOW_EXPLICIT_PROPERTY_RENAMING Feature that when enabled will allow explicitly named properties (i.e., fields or methods annotated with JsonProperty("explicitName")) to be re-named by a PropertyNamingStrategy, if one is configured. Feature is disabled by default.
Since: 2.7
您需要做的就是启用此功能 -
ObjectMapper mapper = new ObjectMapper();
mapper.enable(MapperFeature.ALLOW_EXPLICIT_PROPERTY_RENAMING);
这里是相关的杰克逊笔记历史(参考自here)
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)