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

huangapple go评论90阅读模式
英文:

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

问题

以下是翻译好的部分:

我的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;
}
}

这是我的控制器

@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;
}
}

我的JSP:

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

日志错误:

com.fasterxml.jackson.databind.exc.MismatchedInputException: 无法从对象值(标记JsonToken.START_OBJECT)反序列化类型`[Lcom.forecast.model.Forecast;`
     在[源:(org.springframework.util.StreamUtils$NonClosingInputStream); 行:1,列: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]

如何解决这个问题?非常感谢。

英文:

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:

{

&quot;properties&quot;: {
    &quot;updated&quot;: &quot;2023-06-01T07:20:53+00:00&quot;,
    &quot;units&quot;: &quot;us&quot;,
    &quot;forecastGenerator&quot;: &quot;BaselineForecastGenerator&quot;,
    &quot;generatedAt&quot;: &quot;2023-06-01T08:08:29+00:00&quot;,
    &quot;updateTime&quot;: &quot;2023-06-01T07:20:53+00:00&quot;,
    &quot;validTimes&quot;: &quot;2023-06-01T01:00:00+00:00/P7DT11H&quot;,
    &quot;elevation&quot;: {
        &quot;unitCode&quot;: &quot;wmoUnit:m&quot;,
        &quot;value&quot;: 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(&quot;/test&quot;)
public class ConsumeController {

RestTemplate restTemplate = new RestTemplate();

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

My JSP:

&lt;p&gt;List data: &lt;/p&gt;
&lt;c:forEach items=&quot;${myjson}&quot; var=&quot;myjson&quot;&gt;     
	   	&lt;td&gt;${myjson.name}&lt;/td&gt;
		&lt;td&gt;${myjson.startTime}&lt;/td&gt;		
&lt;/c:forEach&gt;

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

答案1

得分: 0

你的问题在于你的 JSON 结构复杂,而你试图解析其中的嵌套部分。如果我理解正确,你想要反序列化 "properties.periods" 路径下的值,因此你应该改变你的方法。

  1. 手动遍历嵌套结构,达到所需路径
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. 复制响应结构,适当嵌套 Java 对象,并反序列化到父对象(这里仅为简洁起见嵌套了 'Properties' 类,你可以使用简单的类替代)
@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);

注意:在这两种情况下,你应该注意到所需结果中有许多字段是缺失的,所以考虑适当的配置来忽略未知字段。

在你的 POJO 类上使用 @JsonIgnoreProperties(ignoreUnknown = true),或者在 ObjectMapper 上配置 DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES 为 false。

英文:

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&lt;String&gt; responseEntity = restTemplate.getForEntity(&quot;https://api.weather.gov/gridpoints/OKX/33,35/forecast&quot;, String.class);
     ObjectMapper objectMapper = new ObjectMapper();
     JsonNode properties = objectMapper.readTree(responseEntity.getBody()).get(&quot;properties&quot;);
     JsonNode periods = properties.get(&quot;periods&quot;);
     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&lt;Response&gt; responseEntity = restTemplate.getForEntity(&quot;https://api.weather.gov/gridpoints/OKX/33,35/forecast&quot;, 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);

huangapple
  • 本文由 发表于 2023年6月5日 12:36:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/76403515.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定