【问题标题】:Cannot Parse a JSON response that is received by RestTemplate无法解析 RestTemplate 收到的 JSON 响应
【发布时间】:2015-08-25 12:42:27
【问题描述】:

我需要解析从 Web 服务收到的 JSON 响应,但我收到以下错误消息,我对此感到困惑。我在没有结果类的情况下也尝试过,但无济于事。任何帮助将不胜感激。

客户端发送的请求语法错误。

代码

RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new 
                                        MappingJackson2HttpMessageConverter());
        ResponseEntity<Results> responseEntity = restTemplate
                .getForEntity(
                        "http://primesport.sieenasoftware.com/QryApi
                         /GetEvents?
                         username=username&
                         password=password&
                         userid=23",
                         Results.class);
        System.err.println(">>" + responseEntity.getBody().getEvents().size());

结果

public class Results {
    private List<Events> events;
    getter and setter
}

活动

   public class Event {
       private long eventId;
       private String name;
       private String subTitle;
       private String description;
       private String localDate;
       private String localDateFrom;
       private String imageUrl;
       private int venueId;
       private String venue;
       private int availableTickets;
       private long performerId;
       private String performer;
       private String performerType;
       private int subcategoryId;
       private String urlCategoryName;
       private String metaTitle;
       private String metaDescription;
       private String primeSportUrl;
       private String sectionWiseView;
       private String venueCity;
       private String venueState;
       private String snippetDate;
       private int eiProductionId;
       private boolean requireBillingAsShipping;
    public long getEventId() {
        return eventId;
    }
    public void setEventId(long eventId) {
        this.eventId = eventId;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSubTitle() {
        return subTitle;
    }
    public void setSubTitle(String subTitle) {
        this.subTitle = subTitle;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public String getLocalDate() {
        return localDate;
    }
    public void setLocalDate(String localDate) {
        this.localDate = localDate;
    }
    public String getLocalDateFrom() {
        return localDateFrom;
    }
    public void setLocalDateFrom(String localDateFrom) {
        this.localDateFrom = localDateFrom;
    }
    public String getImageUrl() {
        return imageUrl;
    }
    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }
    public int getVenueId() {
        return venueId;
    }
    public void setVenueId(int venueId) {
        this.venueId = venueId;
    }
    public String getVenue() {
        return venue;
    }
    public void setVenue(String venue) {
        this.venue = venue;
    }
    public int getAvailableTickets() {
        return availableTickets;
    }
    public void setAvailableTickets(int availableTickets) {
        this.availableTickets = availableTickets;
    }
    public long getPerformerId() {
        return performerId;
    }
    public void setPerformerId(long performerId) {
        this.performerId = performerId;
    }
    public String getPerformer() {
        return performer;
    }
    public void setPerformer(String performer) {
        this.performer = performer;
    }
    public String getPerformerType() {
        return performerType;
    }
    public void setPerformerType(String performerType) {
        this.performerType = performerType;
    }
    public int getSubcategoryId() {
        return subcategoryId;
    }
    public void setSubcategoryId(int subcategoryId) {
        this.subcategoryId = subcategoryId;
    }
    public String getUrlCategoryName() {
        return urlCategoryName;
    }
    public void setUrlCategoryName(String urlCategoryName) {
        this.urlCategoryName = urlCategoryName;
    }
    public String getMetaTitle() {
        return metaTitle;
    }
    public void setMetaTitle(String metaTitle) {
        this.metaTitle = metaTitle;
    }
    public String getMetaDescription() {
        return metaDescription;
    }
    public void setMetaDescription(String metaDescription) {
        this.metaDescription = metaDescription;
    }
    public String getPrimeSportUrl() {
        return primeSportUrl;
    }
    public void setPrimeSportUrl(String primeSportUrl) {
        this.primeSportUrl = primeSportUrl;
    }
    public String getSectionWiseView() {
        return sectionWiseView;
    }
    public void setSectionWiseView(String sectionWiseView) {
        this.sectionWiseView = sectionWiseView;
    }
    public String getVenueCity() {
        return venueCity;
    }
    public void setVenueCity(String venueCity) {
        this.venueCity = venueCity;
    }
    public String getVenueState() {
        return venueState;
    }
    public void setVenueState(String venueState) {
        this.venueState = venueState;
    }
    public String getSnippetDate() {
        return snippetDate;
    }
    public void setSnippetDate(String snippetDate) {
        this.snippetDate = snippetDate;
    }
    public int getEiProductionId() {
        return eiProductionId;
    }
    public void setEiProductionId(int eiProductionId) {
        this.eiProductionId = eiProductionId;
    }
    public boolean isRequireBillingAsShipping() {
        return requireBillingAsShipping;
    }
    public void setRequireBillingAsShipping(boolean requireBillingAsShipping) {
        this.requireBillingAsShipping = requireBillingAsShipping;
    }

}

部分回复

[{
"EventId":1000250537,
"Name":"US Open Golf",
"SubTitle":null,
"Description":"US Open Golf Tickets",
"Date":"\/Date(1434873560000)\/",
"LocalDate":"6/20/2015 11:59 PM",
"LocalDateFrom":null,
"ImageUrl":null,
"VenueId":146566,
"Venue":"Chambers Bay Golf Course",
"AvailableTickets":33,
"PerformerId":151551,
"Performer":"US Open Golf",
"PerformerType":"Golf",
"SubcategoryId":55,
"UrlCategoryName":"Sports",
"MetaTitle":null,
"MetaDescription":null,
"PrimeSportUrl":"http://primesport.sieenasoftware.com/e/sports/us-open-golf/chambers-bay-golf-course/",
"SectionWiseView":null,
"VenueCity":"UNIVERSITY PLACE",
"VenueState":"WA",
"SnippetDate":null,
"EIProductionId":99985,
"RequireBillingAsShipping":false},
{
"EventId":1000253479,
"Name":"Womens College World Series",
"SubTitle":null,
"Description": .....

更新

我知道 JAXB 可用于 JSON 和 XML,我正在尝试使用它来查看它是否有助于解决问题。

更新

代码返回以下异常:

    org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Can not deserialize instance of com.myproject.myevent.Results out of START_ARRAY token
 at [Source: java.io.PushbackInputStream@dedcd10; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of com.myproject.myevent.Results out of START_ARRAY token
 at [Source: java.io.PushbackInputStream@dedcd10; line: 1, column: 1]
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:208)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:200)
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:97)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:809)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:793)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:576)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:529)
    at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:261)
    at com.myproject.service.TicketSeviceImpl.primeSport(TicketSeviceImpl.java:217)
    at com.myproject.service.TicketSeviceImpl.findTicket(TicketSeviceImpl.java:45)
    at com.myproject.web.TicketController.findTicket(TicketController.java:29)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)

更新

以下代码返回

代码

try {
            System.err.println(">>> primeSport");
            RestTemplate restTemplate = new RestTemplate();
            restTemplate.getMessageConverters().add(
                    new MappingJackson2HttpMessageConverter());
            ResponseEntity<Event[]> responseEntity = restTemplate
                    .getForEntity(
                            "http://primesport.sieenasoftware.com/QryApi/GetEvents?username=username&password=password&userid=23",
                            Event[].class);
            System.err.println(">>" + responseEntity.getBody().length);
            System.err.println(">>" + responseEntity.getBody()[0].getEventId());
            System.err.println(">>" + responseEntity.getBody()[1].getEventId());
        } catch (Exception e) {
            e.printStackTrace();
        }

输出

>1532
>0
>0

【问题讨论】:

  • 您确定您的请求在语法上是正确的吗?我很确定不是。仔细看api
  • 您发布的部分响应不是有效的 json。
  • @muddyfish 请求是正确的,我认为响应有问题,
  • @Jack 尝试在路径 primesport.sieenasoftware.com/QryApi/… 上使用 curl 调用或浏览器直接获取响应,并验证您是否获得了正确的 json。
  • 投反对票的原因是什么?我没有那么聪明,无法做出正确的猜测。聪明并澄清。

标签: java json spring rest jackson


【解决方案1】:

您可以尝试以下方法,看看是否有帮助:

ResponseEntity<Events[]> responseEntity = restTemplate
            .getForEntity(
                    "http://primesport.sieenasoftware.com/QryApi
                     /GetEvents?
                     username=username&
                     password=password&
                     userid=23",
                     Events[].class);
System.err.println(">>" + responseEntity.getBody().length);

为了将字段映射到 JSON 成员,您可以使用 Jackson 注释 JSONProperty("EventId") 可用于 eventId 字段。其他人也一样。

@JsonProperty("EventId")
private long eventId;
@JsonProperty("Name")
private String name;

【讨论】:

  • responseEntity.getBody().length 返回 1532 responseEntity.getBody()[0].getEventId() 返回 null
  • 条目数是否匹配1532? eventID 不是很长吗?检查你的 POJO。我怀疑您将它们转换为字符串(您在某处提到过)。请更改它们以匹配 JSON 响应。
  • 它们都是字符串,我将它们更改为不同的类型,但我仍然收到零。
  • 我包含了事件类 getter/setter 的完整列表,我没有收到来自服务器的事件总数,但我认为这个数字是正确的,否则因为它总是返回相同的数字而不是null 或零。
  • @Jack 查看更新。使用注释可以将您的字段映射到 JSON 结构。
【解决方案2】:

您是否尝试过查看生成的确切请求?比方说在 fiddler/charles 这样的代理软件中?

有时我经历过,在请求真正到达线路(或到达服务器端点)之前,框架会添加额外的构造(编码等)。

试试这个,创建请求。甚至 RestTemplate 的文档也建议避免对 URL 进行双重编码。在 IDE 中查看时可能不是很明显。

String url = "http://primesport.sieenasoftware.com/QryApi/GetEvents?";
MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
params.add("username", "username");
params.add("password", "password");
params.add("userid", "23");

UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(url).queryParams(params).build();
System.out.println(uriComponents.toUri());

请告诉我,结果如何。

另外,如果您找不到设置提琴手代理的步骤,请告知。它是一个非常方便的工具,同时对服务客户端进行编码。

【讨论】:

    【解决方案3】:

    根据 json 格式,你只需要使用 Event 类而不是 Result 类。 或者将 JSON 结果更改为:

    ["events": {
    "EventId":1000250537,
    "Name":"US Open Golf",
    "SubTitle":null,
    "Description":"US Open Golf Tickets",
    "Date":"\/Date(1434873560000)\/",
    "LocalDate":"6/20/2015 11:59 PM",
    "LocalDateFrom":null,
    "ImageUrl":null,
    "VenueId":146566,
    "Venue":"Chambers Bay Golf Course",
    "AvailableTickets":33,
    "PerformerId":151551,
    "Performer":"US Open Golf",
    "PerformerType":"Golf",
    "SubcategoryId":55,
    "UrlCategoryName":"Sports",
    "MetaTitle":null,
    "MetaDescription":null,
    "PrimeSportUrl":"http://primesport.sieenasoftware.com/e/sports/us-open-golf/chambers-bay-golf-course/",
    "SectionWiseView":null,
    "VenueCity":"UNIVERSITY PLACE",
    "VenueState":"WA",
    "SnippetDate":null,
    "EIProductionId":99985,
    "RequireBillingAsShipping":false},
    {
    "EventId":1000253479,
    "Name":"Womens College World Series",
    "SubTitle":null,
    "Description": .....
    

    【讨论】:

      【解决方案4】:

      如果您使用的是 Maven,可以尝试导入 Jackson Jar 或在 pom.xml 中添加依赖项。

      ObjectMapper mapper = new ObjectMapper();
            try
            {
               mapper.writeValue(new File("c://temp/employee.json"), Results);
            }
      

      【讨论】:

      • 我不明白你,哪个依赖?它没有显示缺少任何依赖项。另外我该如何使用您建议的代码?
      猜你喜欢
      • 1970-01-01
      • 2018-06-19
      • 1970-01-01
      • 2016-01-16
      • 1970-01-01
      • 1970-01-01
      • 2022-08-15
      • 1970-01-01
      相关资源
      最近更新 更多