【问题标题】:RESTful Java client convert JSON responses to ObjectsRESTful Java 客户端将 JSON 响应转换为对象
【发布时间】:2019-11-27 15:05:40
【问题描述】:

已编辑:

我正在尝试将从 REST API 服务获得的 JSON 响应转换为我的应用程序内的对象。我使用 Jersey 执行“GET”请求以 REST 服务。

假设我有以下两个 API 调用,每个都有对应的 JSON 响应:

第一次调用:获取特定的 myEntity 对象及其代码值:https://www.test.com/webservice/entity/get?code=BOBS-JC6L (GET)

回应

{
  "isOk": 1,
  "isAuthError": 0,
  "error": false,
  "myEntity":{
        "id": "123",
        "code": "BOBS-JC6L",
        "type": "ZZZ",
        "value": "15.00", 
    }
}

第二次调用:获取所有 myEntity 对象:https://www.test.com/webservice/entity/get-all (GET)

回应

{
  "isOk": 1,
  "isAuthError": 0,
  "error": false,
  "myEntities": [
    {
        "id": "123",
        "code": "BOBS-JC6L",
        "type": "ZZZ",
        "value": "15.00",      
    },
    {
        "id": "456",
        "code": "BOBS-JC7L",
        "type": "CCC",
        "value": "32.00",
    }
    {...}
  ]
}

因此,在这两种情况下,基本对象(MyEntity 类型)都作为嵌套元素包含在 JSON 中。我正在尝试将 JSON 结构映射到 POJO 对象。

所以我创建了以下 POJO 类:

MyEntity POJO(这是基本的嵌套元素类):

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Date;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;

import javax.xml.bind.annotation.XmlRootElement;

public class MyEntity {

    private int id;
    private String code;
    private String type;
    private BigDecimal value;

    public MyEntity(){

    }

    public MyEntity(String code, String type, BigDecimal value){
        this.code = code;
        this.type = type;
        this.value = value;
    }

    ....

}

然后有一个用于第一个 API 调用响应的类(我们得到一个 MyEntity 对象):

@XmlRootElement
public class GetSingleMyEntityResponse {

    private int isOk;
    private int isAuthError;
    private boolean error;
    private MyEntity myEntity;

    ...

}

第二个 API 调用响应的另一个类(我们得到多个嵌套的 MyEntity 对象):

@XmlRootElement
public class GetMultipleMyEntityResponse {

    private int isOk;
    private int isAuthError;
    private boolean error;
    private List<MyEntity> myEntities;

    ...

}

在我的代码中,我首先尝试获取单个 myEntity 对象,调用:https://www.test.com/webservice/entity/get?code=BOBS-JC6L

try {

      ClientConfig clientConfig = new DefaultClientConfig();
      Client client = Client.create(clientConfig);

      WebResource webResource1 = client
              .resource("https://www.test.com/webservice/entity/get?code=MESM-ZB2NEJ");

      Builder builder = webResource1.accept(MediaType.APPLICATION_JSON) //
              .header("content-type", MediaType.APPLICATION_JSON);

      ClientResponse response = builder.get(ClientResponse.class);

      // Status 200 is successful.
      if (response.getStatus() != 200) {
          System.out.println("Failed with HTTP Error code: " + response.getStatus());
          String error = response.getEntity(String.class);
          System.out.println("Error: " + error);
          return;
      }

      System.out.println("\n\nOutput from Server .... \n");

      GetSingleMyEntityResponse vResp = (GetSingleMyEntityResponse) response.getEntity(GetSingleMyEntityResponse.class);
      MyEntity v = vResp.getMyEntity();

      if(v.getId()>0) {
          System.out.println("Id .... " + v.getId());
          System.out.println("Code .... " + v.getCode());
          System.out.println("Type .... " + v.getType());      
          System.out.println("Value .... " + v.getValue());
      }
    } catch (Exception e) {
        e.printStackTrace();
}

这行得通,我可以得到 MyEntity 对象:

Output from Server .... 

Id .... 123
Code .... BOBS-JC6L
Type .... ZZZ
Value .... 15.00

我还尝试从以下位置映射多个 MyEntity 对象: https://www.test.com/webservice/entity/get-all

try {

            Client client = Client.create();

            WebResource webResource = client
               .resource("https://www.test.com/webservice/entity/get-all");

            ClientResponse response = webResource.accept("application/json")
                       .get(ClientResponse.class);

            if (response.getStatus() != 200) {
               throw new RuntimeException("Failed : HTTP error code : "
                + response.getStatus());
            }

            String output = response.getEntity(String.class);

            GetMultipleMyEntityResponse vResp = (GetMultipleMyEntityResponse) response.getEntity(GetMultipleMyEntityResponse.class);
            List<MyEntity> vRespList = new ArrayList<>();
            vRespList = vResp.getMyEntities();

            if(vRespList.size()>0) {

                for(MyEntity v:vRespList) {
                    System.out.println("Id .... " + v.getId());
                    System.out.println("Code .... " + v.getCode());
                    System.out.println("Type .... " + v.getType());      
                    System.out.println("Value .... " + v.getValue());
                }

            }

          } catch (Exception e) {

            e.printStackTrace();

}

但似乎 GetMultipleMyEntityResponse POJO 类不适用于它,我得到:

j

avax.ws.rs.WebApplicationException: HTTP 400 Bad Request
    at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:113)
    at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:553)
    at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:506)
    at com.mspos.mesmo.JerseyClientGet.main(JerseyClientGet.java:97)
Caused by: javax.xml.bind.UnmarshalException: Error creating JSON-based XMLStreamReader
 - with linked exception:
[javax.xml.stream.XMLStreamException: java.io.IOException: stream is closed]
    at com.sun.jersey.json.impl.BaseJSONUnmarshaller.createXmlStreamReader(BaseJSONUnmarshaller.java:116)
    at com.sun.jersey.json.impl.BaseJSONUnmarshaller.unmarshalJAXBElementFromJSON(BaseJSONUnmarshaller.java:108)
    at com.sun.jersey.json.impl.BaseJSONUnmarshaller.unmarshalFromJSON(BaseJSONUnmarshaller.java:97)
    at com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider.readFrom(JSONRootElementProvider.java:125)
    at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:111)
    ... 3 more
Caused by: javax.xml.stream.XMLStreamException: java.io.IOException: stream is closed
    at com.sun.jersey.json.impl.Stax2JsonFactory.ensureNonEmptyReader(Stax2JsonFactory.java:173)
    at com.sun.jersey.json.impl.Stax2JsonFactory.createReader(Stax2JsonFactory.java:117)
    at com.sun.jersey.json.impl.Stax2JsonFactory.createReader(Stax2JsonFactory.java:111)
    at com.sun.jersey.json.impl.BaseJSONUnmarshaller.createXmlStreamReader(BaseJSONUnmarshaller.java:113)
    ... 7 more
Caused by: java.io.IOException: stream is closed
    at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.ensureOpen(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(Unknown Source)
    at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
    at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
    at sun.nio.cs.StreamDecoder.read(Unknown Source)
    at java.io.InputStreamReader.read(Unknown Source)
    at java.io.BufferedReader.fill(Unknown Source)
    at java.io.BufferedReader.read(Unknown Source)
    at com.sun.jersey.json.impl.Stax2JsonFactory.ensureNonEmptyReader(Stax2JsonFactory.java:167)
    ... 10 more

关于我缺少什么的任何想法?

【问题讨论】:

  • 您使用 Jersey 客户端而不是 Spring RestTemplate 或 Retrofit 是否有特定原因?
  • 我是 RESTful 的 Java 新手,乍一看,这对我来说似乎很简单。我会看看您的建议并感谢您提供的信息!
  • 您的回复显然与 MyEntity 的结构不符。查看 JSON:您收到的对象不是 MyEntity。它是一个 MyEntity 包装到另一个对象的字段 isOk、error 等。
  • 你是对的@JBNizet ...我明白了。所以也许我可以通过使用 Jakson 对象映射器之类的东西来获取我需要的部分 JSON:baeldung.com/jackson-object-mapper-tutorial
  • 您可能已经使用它(或等效的),因为 Jersey 已经将 JSON 映射到一个对象。但是你需要使用正确的类,它与响应的结构相匹配。

标签: java json rest web-services jersey


【解决方案1】:

您拨打了两次response.getEntity()。只调用一次。

【讨论】:

    猜你喜欢
    • 2017-10-17
    • 2018-02-28
    • 1970-01-01
    • 2014-06-18
    • 2018-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多