JSON解析错误:无法从START_ARRAY令牌中反序列化``的实例

时间:2019-12-10 07:55:21

标签: java json api spring-boot jackson

我是Spring Boot和API的新手,尽管我的Spring Boot应用程序已与MySql数据库连接,但我正在一个项目中需要从公共API提取数据并将其存储到本地数据库。从API提取数据时,我的编译器抛出了一个异常:

Error while extracting response for type [class com.currencyExchangeRates.models.CurrencyDTO] and content type [application/json;charset=utf-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `com.currencyExchangeRates.models.CurrencyDTO` out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `com.currencyExchangeRates.models.CurrencyDTO` out of START_ARRAY token at [Source: (PushbackInputStream); line: 1, column: 1]

我的一般想法是从公共API获取数据并将其存储在本地数据库中,然后根据我的项目要求使用这些数据。

我已经尝试了Google以及StackOverflow的几乎所有解决方案,但我没有任何想法。

我正在尝试获取的JSON格式:

[
   {
      "table":"A",
      "no":"237/A/NBP/2019",
      "effectiveDate":"2019-12-09",
      "rates":[
         {
            "currency":"bat (Tajlandia)",
            "code":"THB",
            "mid":0.1277
         },
         {
            "currency":"dolar amerykański",
            "code":"USD",
            "mid":3.8704
         }
      ]
   }
]

在这里,我的CurrencyDTO类:

public class CurrencyDTO {

    private String table;
    private String num;
    private String date;

    private Rates rates;

    // Getters and Setters, No-arg/arg constractor

Rates.java

public class Rates {

    private String currency;
    private Map<String, Double> price;

    // Getters and Setters, No-arg/arg constractor

我调用API的代码段:

try {
            RestTemplate restTemplate = new RestTemplate();

            CurrencyDTO forObject = 
                    restTemplate.getForObject("http://api.nbp.pl/api/exchangerates/tables/a/", CurrencyDTO.class);

                forObject.getRates().getPrice().forEach((key, value) -> {
                Currency currency = new Currency(key, value);
                this.currencyRepository.save(currency); 
            });
        }catch (RestClientException ex) {
            System.out.println(ex.getMessage());
        }

控制器类:

@GetMapping("/currency")
    public List<Currency> findAll(){
        return currencyService.getAllCurrencies();
    }

2 个答案:

答案 0 :(得分:2)

此外,您共享的json是CurrencyDTO数组。假设您的Json是,

  {
      "table":"A",
      "no":"237/A/NBP/2019",
      "effectiveDate":"2019-12-09",
      "rates":[
         {
            "currency":"bat (Tajlandia)",
            "code":"THB",
            "mid":0.1277
         },
         {
            "currency":"dolar amerykański",
            "code":"USD",
            "mid":3.8704
         }
      ]
   }

将CurrencyDTO更改为

@Data
@NoArgsConstructor
public class CurrencyDTO {

    private String table;
    private String no;
    private String effectiveDate;

    private List<Rates> rates;
}

和您的Rates类,

@Data
@NoArgsConstructor
public class Rates {

    private String currency;
    private String code;
    private Double mid;
}

它能够为我反序列化。 您在做错什么是Dto实例变量应该根据Json中的名称,或者您应该使用 @JsonProperty(“ nameInTheJson”)

如果要使其与JSON兼容,则可以使用CurrencyDTO数组 您将可以反序列化,可以将对象用作

try {
       RestTemplate restTemplate = new RestTemplate();

       CurrencyDTO[] forObject =
                    restTemplate.getForEntity("http://api.nbp.pl/api/exchangerates/tables/a/", CurrencyDTO[].class).getBody();
          for (CurrencyDTO currencyDTO1 : forObject) {
                for (Rates rate : currencyDTO1.getRates()) {
                    Currency currency = new Currency(rate.getCode(), rate.getMid());
                    //you code to put the object inside the db
                    this.currencyRepository.save(currency);
                }
            }
        }catch (Exception ex) {
            System.out.println(ex.getMessage());
        }

答案 1 :(得分:1)

首先,您的JSON是一个CurrencyDTO数组,而不仅仅是注释中提到的CurrencyDTO,现在,如果它影响代码的其他部分,并且您只想反序列化它,则可以执行以下操作:

CurrencyDTO[] forObject = new ObjectMapper.readValue(restTemplate.getForEntity("http://api.nbp.pl/api/exchangerates/tables/a/", CurrencyDTO[].class).getBody() , new TypeReference<List<CurrencyDTO>>() {}).get(0);

此外,我强烈建议您这样做是最糟糕的方法。最好更新API以返回正确的响应。