使用 RestEasy 处理 JSON 没有 'root' 元素的响应
Handle JSON Response that comes without 'root' element with RestEasy
我调用一些 Web 服务(在 Ruby 中构建)并得到 JSON 响应,如下所示:
{
"error_code": "02",
"message": "Param not valid",
"field_name": "title"
}
为了在 Java 中对响应对象进行建模,我尝试使用:
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "response")
public class Response {
private String error_code;
private String message;
private String field_name;
public String getError_code() {
return error_code;
}
public void setError_code(String error_code) {
this.error_code = error_code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getField_name() {
return field_name;
}
public void setField_name(String field_name) {
this.field_name = field_name;
}
}
...并在我的 WS 客户端中读取 WS 调用的响应,我尝试:
Response response = responseWs.readEntity(Response.class);
...但出现以下异常:
org.jboss.resteasy.plugins.providers.jaxb.JAXBUnmarshalException: javax.xml.bind.UnmarshalException
- with linked exception:
[com.sun.istack.internal.SAXParseException2; columnNumber: 0 unexpected element ... Expected elements are
那是因为我的代码试图像这样处理 JSON 响应对象(带有一些 'root' 元素):
{
"response":
{
"error_code": "02",
"message": "Param not valid",
"field_name": "title"
}
}
有人知道我该如何解决这种情况吗?
谢谢
在那里配置 JAXB(属性文件或配置方法),您应该设置
jaxbUnmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false)
对我来说,这个片段解决了这个问题:
String responseAsString = responseWs.readEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
JsonNode pathNode = mapper.readTree(responseAsString);
Response response = mapper.convertValue(pathNode, Response.class);
来自您发布的代码片段
Response response = responseWs.readEntity(Response.class);
我建议为您的实体对象使用其他名称。 Response
class 也是jaxrs框架自己使用的
我假设您正在使用 RestEasyClient
调用此(外部)服务来接收 JSON。如果了解到此服务的响应在 JSON 中,则可以使用 JSON (jackson) marshaller/unmarshaller 代替 JAXB。假设您的 class 路径上已经有 "resteasy-client" 依赖项可用。此依赖项的 Maven 形式如下所示:
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>3.0.19.Final</version>
</dependency>
- 将 DTO 的名称更改为
ExternalServiceResponse
- 在执行
GET
请求时明确指定响应媒体类型
Response response = target.request(MediaType.APPLICATION_JSON).get();
ExternalServiceResponse result = response.readEntity(ExternalServiceResponse.class)
- 最后我不明白为什么你需要在 DTO 上指定
@XmlRootElement
注释
public class ExternalServiceResponse implements Serializeable {
private String error_code;
private String message;
private String field_name;
public String getError_code() {
return error_code;
}
public void setError_code(String error_code) {
this.error_code = error_code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getField_name() {
return field_name;
}
public void setField_name(String field_name) {
this.field_name = field_name;
}
}
我调用一些 Web 服务(在 Ruby 中构建)并得到 JSON 响应,如下所示:
{
"error_code": "02",
"message": "Param not valid",
"field_name": "title"
}
为了在 Java 中对响应对象进行建模,我尝试使用:
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "response")
public class Response {
private String error_code;
private String message;
private String field_name;
public String getError_code() {
return error_code;
}
public void setError_code(String error_code) {
this.error_code = error_code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getField_name() {
return field_name;
}
public void setField_name(String field_name) {
this.field_name = field_name;
}
}
...并在我的 WS 客户端中读取 WS 调用的响应,我尝试:
Response response = responseWs.readEntity(Response.class);
...但出现以下异常:
org.jboss.resteasy.plugins.providers.jaxb.JAXBUnmarshalException: javax.xml.bind.UnmarshalException - with linked exception: [com.sun.istack.internal.SAXParseException2; columnNumber: 0 unexpected element ... Expected elements are
那是因为我的代码试图像这样处理 JSON 响应对象(带有一些 'root' 元素):
{
"response":
{
"error_code": "02",
"message": "Param not valid",
"field_name": "title"
}
}
有人知道我该如何解决这种情况吗?
谢谢
在那里配置 JAXB(属性文件或配置方法),您应该设置
jaxbUnmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false)
对我来说,这个片段解决了这个问题:
String responseAsString = responseWs.readEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
JsonNode pathNode = mapper.readTree(responseAsString);
Response response = mapper.convertValue(pathNode, Response.class);
来自您发布的代码片段
Response response = responseWs.readEntity(Response.class);
我建议为您的实体对象使用其他名称。 Response
class 也是jaxrs框架自己使用的
我假设您正在使用 RestEasyClient
调用此(外部)服务来接收 JSON。如果了解到此服务的响应在 JSON 中,则可以使用 JSON (jackson) marshaller/unmarshaller 代替 JAXB。假设您的 class 路径上已经有 "resteasy-client" 依赖项可用。此依赖项的 Maven 形式如下所示:
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>3.0.19.Final</version>
</dependency>
- 将 DTO 的名称更改为
ExternalServiceResponse
- 在执行
GET
请求时明确指定响应媒体类型
Response response = target.request(MediaType.APPLICATION_JSON).get();
ExternalServiceResponse result = response.readEntity(ExternalServiceResponse.class)
- 最后我不明白为什么你需要在 DTO 上指定
@XmlRootElement
注释
public class ExternalServiceResponse implements Serializeable {
private String error_code;
private String message;
private String field_name;
public String getError_code() {
return error_code;
}
public void setError_code(String error_code) {
this.error_code = error_code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getField_name() {
return field_name;
}
public void setField_name(String field_name) {
this.field_name = field_name;
}
}