有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java JSON解析错误:无法反序列化“`out of START_数组令牌”的实例

我不熟悉Spring Boot和API,我正在从事一个项目,需要从公共API获取数据并将其存储到本地数据库,尽管我的Spring Boot应用程序与MySql数据库相连。从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获取数据并将其存储在本地数据库中,然后根据我的项目要求使用这些数据

我尝试过谷歌和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
         }
      ]
   }
]

下面是我的课程:

public class CurrencyDTO {

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

    private Rates rates;

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

费率。爪哇

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) 个答案

  1. # 1 楼答案

    此外,您共享的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
             }
          ]
       }
    

    把你的货币换成

    @Data
    @NoArgsConstructor
    public class CurrencyDTO {
    
        private String table;
        private String no;
        private String effectiveDate;
    
        private List<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());
            }
    
  2. # 2 楼答案

    首先,你的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以返回正确的响应