【问题标题】:Spring Rest service @RequestBody nested json parsing failedSpring Rest服务@RequestBody嵌套json解析失败
【发布时间】:2017-12-28 08:17:04
【问题描述】:
  • 春季 4.3.2
  • 杰克逊 2.7.0

我已经使用 spring rest 创建了微服务。我要求 RequestBody 应该有一个嵌套的 json。

RequestWrapper.java:

public class RequestWrapper implements Serializable{ 
private String id;
private String message; // json in string format
/**
getter & setter
**/
}

消息属性是动态的,例如,对于一个请求,它可能具有“Person”对象的 json,对于另一个请求,它可能具有不同的对象。

当我将嵌套的 json 作为字符串并随后转换为实际对象时,一切正常 例如:

{
"id":"sample",
"message":"{\"age\":\"12\"}"
}

控制器示例:

@Controller
@EnableWebMvc
public class RequestController{
@RequestMapping(value = "/request.htm", method = RequestMethod.POST, headers = "Accept=*/*", consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseWrapper handleRequest(@RequestBody RequestWrapper requestWrapper,
        HttpServletResponse response) {
ResponseWrapper responseWrapper = new ResponseWrapper();
ObjectMapper mapper = new ObjectMapper();
Person person= mapper.readValue(requestWrapper.getMessage(), Person.class);
    }
}

Junit 测试用例也用这种方法成功执行。

现在我修改了 RequestWrapper.java,将消息属性的类型设为 Object 而不是 String

public class RequestWrapper<Object extends Serializable> implements Serializable{
private String id;
    private Object message; // Changed to Object
    /**
    getter & setter
    **/
    }

改变了Controller类如下

@Controller
@EnableWebMvc
public class CipherController{
@RequestMapping(value = "/request.htm", method = RequestMethod.POST, headers = "Accept=*/*", consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseWrapper handleRequest(@RequestBody RequestWrapper requestWrapper,
        HttpServletResponse response) {
ResponseWrapper responseWrapper = new ResponseWrapper();
ObjectMapper mapper = new ObjectMapper();
Person person= (Person)requestWrapper.getMessage();
}
}

新的 json 格式现在如下所示:

例如:

{
"id":"sample",
"message":{"age":"12"}
}

当我执行 Junit 测试用例时,我得到以下异常

WARNING: Failed to read HTTP message: 

org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Can not construct instance of java.io.Serializable, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information
 at [Source: java.io.PushbackInputStream@3e58d65e; line: 1, column: 115] (through reference chain: com.common.model.RequestWrapper["message"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.io.Serializable, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information

pom.xml 中的杰克逊依赖

<dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.7.0</version>
     </dependency>
     <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.7.0</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.7.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.codehaus.jackson/jackson-core-asl -->
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>1.9.13</version>
</dependency>
    <!-- https://mvnrepository.com/artifact/org.codehaus.jackson/jackson-mapper-asl -->
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
</dependency>

我假设 Jackson 解析器无法识别嵌套的 json(message) 应该映射到哪个对象实例,但我不知道如何解决这个问题。

【问题讨论】:

    标签: json jackson spring-rest


    【解决方案1】:

    错误消息向您提供了问题,甚至告诉您确切的位置。

    line: 1, column: 115] (通过引用链: com.common.model.RequestWrapper["message"]);

    无法构造 java.io.Serializable 的实例,问题:抽象类型要么需要 映射到具体类型,具有自定义反序列化器,或者是 用额外的类型信息实例化

    让你的域对象扩展 Serializable 是没有意义的。

    除此之外,您将方法字段类型更改为 Object 并设置了一个“age”子字段,该字段在 Object.class 中不作为字符串字段存在。没有办法对此进行映射,对于该域对象来说,除了 JSON 之外没有什么是合法的,而它本身的域对象是不合法的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-14
      • 1970-01-01
      • 1970-01-01
      • 2013-07-22
      • 1970-01-01
      • 2017-06-22
      • 2017-12-17
      相关资源
      最近更新 更多