java - 为什么我的 Jax-RS 客户端对象不反序列化此 HTTP 响应中的 JSON 列表,即使对象映射器可以反序列化?
问题描述
我开始为 REST API 编写客户端,并从一个简单的调用开始,该调用返回一个相对简单的 JSON 对象:一个resultCode
字符串、一个message
字符串和一个对象列表。当我首先将对象作为字符串检索并使用 解码时ObjectMapper
,它会很好地解组,包括对象列表。但是,当我使用Client
对象检索它时,它只检索字符串属性,而不是对象列表。我想对比这更复杂的 API 响应进行建模,但我认为在我克服这个障碍之前这是不明智的。
我尝试过使用注释,例如使用注释创建setResultItems
方法@JsonSetter
。我最初的示例使用了 getter 和 setter,但我发布的示例使用公共字段来节省空间——结果是一样的。我还尝试通过向对象注册 a来强制Client
对象使用相同的。我注意到的一件事是调用立即设置所有内容的构造函数,但需要一个无参数构造函数,并在创建对象后设置属性。ObjectMapper
JacksonJsonProvider
ObjectMapper
Client
这是响应对象类的最简单版本:
class ResponseObject {
public String resultCode;
public String message;
public List<Map<String,String>> resultItems;
ResponseObject() {
System.out.println("Blank constructor called");
}
ResponseObject(
@JsonProperty("resultItems") List<Map<String,String>> resultItems,
@JsonProperty("message") String message,
@JsonProperty("resultCode") String resultCode ) {
System.out.println("Good constructor called");
this.resultCode = resultCode;
this.message = message;
this.resultItems = resultItems;
}
private void print() {
System.out.println("resultCode: " + resultCode);
System.out.println("message: " + message);
System.out.println("resultItems: " + resultItems.toString());
}
}
我的测试应用程序在 try-catch 中运行此方法:
private static void doGetVariable() throws IOException {
Client client = ClientBuilder.newClient();
// hey this means the client should decode it the same way right?
ObjectMapper mapper = new ObjectMapper();
JacksonJsonProvider provider = new JacksonJsonProvider(mapper);
client.register(provider);
System.out.println("Getting string and deserializing it");
String sresp = client.target(URL)
.request(MediaType.APPLICATION_JSON)
.get(String.class);
System.out.println("string: "+sresp);
ResponseObject resp1 = mapper.readValue(sresp, ResponseObject.class);
resp1.print();
System.out.flush();
System.out.println("\nGetting object directly from the client");
ResponseObject resp2 = client.target(URL)
.request(MediaType.APPLICATION_JSON)
.get(ResponseObject.class);
resp2.print();
}
由于这些事情似乎很重要,因此这是我pom.xml
文件中的依赖项。我必须添加 Jersey 的,因为如果我不添加,我会得到 aClassNotFoundException
因为它找不到JerseyClientBuilder
. 我认为这是一个提示,但我不确定这意味着什么。
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1.1</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext.rx</groupId>
<artifactId>jersey-rx-client</artifactId>
<version>2.25.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.25.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.9.9</version>
</dependency>
当我运行它时,这是输出。您可以在以string:
. 我希望resultItems
这两个请求都是一样的,但它只在第一个请求中是正确的。请注意,它仍然设置resultCode
并且message
在两次尝试中,所以它至少在做一些事情。
Getting string and deserializing it
string: {"resultItems":[{"name":"MAX.PACKETSIZE","value":"64512"}],"message":"OK - the variables were successfully retrieved","resultCode":"0"}
Good constructor called
resultCode: 0
message: OK - the variables were successfully retrieved
resultItems: [{name=MAX.PACKETSIZE, value=64512}]
Getting object directly from the client
Blank constructor called
resultCode: 0
message: OK - the variables were successfully retrieved
resultItems: []
此外,我更愿意摆脱无参数构造函数,以便我可以制作所有字段private final
并正确封装所有内容。
解决方案
推荐阅读
- angular - Angular 8:ngx-chips 表单验证问题
- java - 覆盖父类的方法
- spring-boot - springData Jpa中的自定义查询
- excel - If 和 Loop 函数提取数据
- python - python程序给出了两种不同的输出
- ionic-framework - Ionic 4 中的 ion-searchbar 在浏览器控制台上抛出未找到图标的错误
- swift - Swift中非集合类型的`map`函数
- c++ - 从二维数组中减去 min
- java - 使用spring boot和apache camel从oracle队列中读取消息
- javascript - TypeScript:'Card | 类型的参数 undefined' 不能分配给'Card' 类型的参数