使用外部 API 并从 JSON 字符串转换为 bean 不会初始化属性。 NULL 对象属性。 Spring 引导,Maven

Consuming external API and converting from JSON string to bean doesn't initialize properties. NULL object attributes. Spring Boot, Maven

这是我从 API 得到的回复。

{"get":"statistics","parameters":{"country":"romania"},"errors":[],"results":1,"response":[{"continent" :"Europe","country":"Romania","population":19016885,"cases":{"new":"+4521","active":156487,"critical":431,"recovered":2606660 ,"1M_pop":"148707","总计":2827936},"死亡人数":{"新":"+35","1M_pop":"3407","总计": 64789},“测试”:{“1M_pop”:“1149381”,“总计”:21857638},“天”:“2022-03-24”,“时间”:“2022-03-24T07: 30:04+00:00"}]}

@RestController
public class CovidTrackerRestController {
    
    @GetMapping("/hello")
    public String showCovidInformation() {
        
        // connect to a covid database
                        
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://covid-193.p.rapidapi.com/statistics?country=romania"))
                .header("X-RapidAPI-Host", "covid-193.p.rapidapi.com")
                .header("X-RapidAPI-Key", "mykey")
                .method("GET", HttpRequest.BodyPublishers.noBody())
                .build();
        HttpResponse<String> response = null;
        
        try {
            response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
        } catch (IOException | InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
                        
        // get the information
        String responseString = response.body();
        System.out.println(responseString);
        
        Response romaniaData = null;
        
        try {
            romaniaData = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
                            .readValue(responseString, Response.class);
        } catch (JsonProcessingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
            
        
        // format the information
        System.out.println(romaniaData);
                
        
        // send the information to html page
        return "/tracker";
    }
}

这是我的 Bean class,它在配置器 class 中用 @Bean 与 RestTemplate bean 一起注释。除了在配置器中被声明为 @Bean 之外,其他属性(例如 Cases、Deaths 等)的配置与 Response class 相同,因为据我所知,一旦我声明了一个 class @Bean,其他包含的引用就会自动成为 beans还有。

@JsonIgnoreProperties(ignoreUnknown = true)
public class Response {

    @JsonProperty("country")
    private String country;
    
    @JsonProperty("cases")
    private Cases cases;
    
    @JsonProperty("deaths")
    private Deaths deaths;
    
    @JsonProperty("day")
    private String day;
    
    @JsonProperty("time")
    private String time;
    
    @JsonProperty("test")
    private Tests tests;
    
    public String getCountry() {
        return country;
    }
    public void setCountry(String country) {
        this.country = country;
    }

您的 java class 需要准确表示收到的 json。我们称它为 Wrapper:

public class Wrapper {

    @JsonProperty("response")
    private List<Response> responses;

    public List<Response> getResponses() {
        return this.responses;
    }

    public void setResponses(List<Response> responses) {
        this.responses = responses;
    }

    @Override
    public String toString() {
        return "Wrapper{" +
                "responses=" + responses +
                '}';
    }
}

我省略了一些属性 - getresults 等。看来您不需要它们。然后反序列化将如下所示:

Wrapper data = null;
try {
    data = new ObjectMapper()
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            .readValue("json", Wrapper.class);
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
System.out.println(data);

几点注意事项:

  1. 如果json属性名称匹配class中的字段名称,则不需要@JsonProperty
  2. 对于测试字段注释应该是 - @Json属性("tests")。 属性 是 tests,而不是 test

如果你真的想扔掉剩下的数据,并且只需要response属性,那么你需要编写自定义反序列化器并处理json树。例如,您可以在 my answer here, or this guide 中查看如何操作。像这样您可以将响应 json 解析为您的 class,即使它们的结构不匹配。

是的,你的class应该是这样的:

public class ResponseWrapper {
  public List<Response> response;

  public setResponse(List<Response> response) {
    this.response= response;
  }
  public List<Response> getResponse() {
    return response;
  }
}

而 class Response 是您发布时的 class。您的 class 必须具有与 JSON

相同的结构