我正在使用 Spring Boot 3.2.2 在 Java 17 中制作 REST API。我的 API 调用外部 REST API。所说的 API,尽管它确实返回一个 json,但它并没有以典型的方式执行。它返回的是 json string,而不是 json object。
这个:
"{\"Code\":\"123-456\",\"Number\":1}"
不是这个:
{
"Code": "123-456",
"Number": 1
}
我有一个课程来获取回复:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ApiResponse {
@JsonProperty("Code")
private String code;
@JsonProperty("Number")
private String number;
}
现在使用此代码:
ApiResponse response = restClient.post()
.uri(url)
.contentType(MediaType.APPLICATION_JSON)
.body(request.toJsonString())
.retrieve()
.body(ApiResponse.class);
这个替代代码:
String responseBody = restClient.post()
.uri(url)
.contentType(MediaType.APPLICATION_JSON)
.body(request.toJsonString())
.retrieve()
.body(String.class);
ApiResponse response;
try {
response = objectMapper.readValue(responseBody, ApiResponse);
} catch(...) {
...
}
return response;
在这两种情况下,它都在反序列化部分失败。在第一种情况下,它在
.body(...)
中,在第二种情况下,它在 objectMapper.readValue(...)
中。
抛出的异常是:
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `com.example.test.models.ApiResponse` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"Code":"123-456","Number":1}')
同样,有问题的 json 字符串是:
"{\"Code\":\"123-456\",\"Number\":1}"
我似乎无法将其反序列化到类中。我是不是错过了什么?
您得到的字符串是对符号
"
进行转义的。因此,您看到的不是 "
,而是 \"
,如果您想在字符串中包含符号 "
,则必须在代码中键入该内容。因此,在您的代码中运行代码,将每次出现的 \"
替换为 "
,然后在新字符串上运行代码,这应该可以工作。因此,将您的代码更改为:
try {
responseBody = responseBody .replace("\\\"", "\"");
response = objectMapper.readValue(responseBody, ApiResponse);
} catch(...) {
...
}
这应该可以解决您的问题。 另外,我编写了一个小实用程序,可以帮助您序列化和反序列化 Json,它是
ObjectMapper
类的薄包装器。它允许您只调用一些静态方法,而无需实例化 ObjectMapper
类。在这种情况下,您可以在代码中替换该行
response = objectMapper.readValue(responseBody, ApiResponse);
用线:
response = JsonUtils.readObjectFromJsonString(responseBody, ApiResponse);
如果您感兴趣,请参阅JsonUtils 类的 Javadoc。它是我编写和维护的开源 MgntUtils 库的一部分。您可以从 Maven Central 获取该库作为 Maven 工件,或者从 Github
获取 Jar(也提供源代码和 Javadoc)