使用 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>

  1. 将 DTO 的名称更改为 ExternalServiceResponse
  2. 在执行 GET 请求时明确指定响应媒体类型
Response response = target.request(MediaType.APPLICATION_JSON).get();
ExternalServiceResponse result = response.readEntity(ExternalServiceResponse.class)
  1. 最后我不明白为什么你需要在 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;
    }

}