Khanh Luong Van
Khanh Luong Van

Reputation: 515

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `[]` from Object value (token `JsonToken.START_OBJECT`)

I have tried everything to read the following JSON string, but I still get the below error. My JSON string is valid and I think the issue is that the sub element is having problem with the mapping.

Here is my JSON string:

{

"properties": {
    "updated": "2023-06-01T07:20:53+00:00",
    "units": "us",
    "forecastGenerator": "BaselineForecastGenerator",
    "generatedAt": "2023-06-01T08:08:29+00:00",
    "updateTime": "2023-06-01T07:20:53+00:00",
    "validTimes": "2023-06-01T01:00:00+00:00/P7DT11H",
    "elevation": {
        "unitCode": "wmoUnit:m",
        "value": 2.1335999999999999      
}
}

My Java POJO

@JsonIgnoreProperties
public class Forecast {

private int number;
private String name;
private String startTime;
private String endTime;

public int getNumber() {
    return number;
}

public void setNumber(int number) {
    this.number = number;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getStartTime() {
    return startTime;
}

public void setStartTime(String startTime) {
    this.startTime = startTime;
}

public String getEndTime() {
    return endTime;
}

public void setEndTime(String endTime) {
    this.endTime = endTime;
}
}

This is my controller

@Controller
@RequestMapping("/test")
public class ConsumeController {

RestTemplate restTemplate = new RestTemplate();

@RequestMapping("/show")
public ModelAndView showForecast() {
    
    ModelAndView mv = new ModelAndView();
    mv.setViewName("show");
    
    ResponseEntity<Forecast[]> responseEntity = restTemplate.getForEntity("https://api.golde.gov", Forecast[].class);
    Forecast[] responseBody = responseEntity.getBody();     
    
    List<Forecast> allForeCast = Arrays.asList(responseBody);
    mv.addObject("myjson", allForeCast);
    
    System.out.println("data: " + allForeCast);
    
    return mv;
}   
}

My JSP:

<p>List data: </p>
<c:forEach items="${myjson}" var="myjson">     
        <td>${myjson.name}</td>
        <td>${myjson.startTime}</td>        
</c:forEach>

Logger error:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `[Lcom.forecast.model.Forecast;` from Object value (token `JsonToken.START_OBJECT`)
 at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 1]
 at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59) ~[jackson-databind-2.15.0.jar:2.15.0]
 at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1752) ~[jackson-databind-2.15.0.jar:2.15.0]
 at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1526) ~[jackson-databind-2.15.0.jar:2.15.0]
 at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1473) ~[jackson-databind-2.15.0.jar:2.15.0]

How to fix them problem? many thank

Upvotes: 1

Views: 10441

Answers (1)

Irremediable
Irremediable

Reputation: 168

Your problem is that your json has a complex structure and you are trying to parse its nested part. If I get it correct, you want to deserialize values under "properties.periods" path, so you should change approach you to use.

  1. Manually walk through the nested structure, reaching the desired path

     ResponseEntity<String> responseEntity = restTemplate.getForEntity("https://api.weather.gov/gridpoints/OKX/33,35/forecast", String.class);
     ObjectMapper objectMapper = new ObjectMapper();
     JsonNode properties = objectMapper.readTree(responseEntity.getBody()).get("properties");
     JsonNode periods = properties.get("periods");
     Forecast[] forecasts = objectMapper.readValue(periods.toString(), Forecast[].class);
    
  1. Reproduce the response structure with the appropriate nesting of java objects, and deserialize to the parent object (Nested 'Properties' class here only for shorteness, you're good to use simple one instead)

     @Data
     public class Response {
    
       private Properties properties;
    
       @Data
       public static class Properties {
         private Forecast[] periods;
       }
     }
    
     //
    
     ResponseEntity<Response> responseEntity = restTemplate.getForEntity("https://api.weather.gov/gridpoints/OKX/33,35/forecast", Response.class);
    

NOTE: In both cases you should take to attention that many fields are absent in desired result, so consider proper configuration to ignore unknown fields.

@JsonIgnoreProperties(ignoreUnknown = true) 

on your POJO classes, or

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

Upvotes: 0

Related Questions