【问题标题】:JSON parse error: Can not construct instance of io.starter.topic.TopicJSON 解析错误:无法构造 io.starter.topic.Topic 的实例
【发布时间】:2018-07-05 00:13:31
【问题描述】:

我正在学习 Spring Boot,我做了一个演示,但是当我发布添加对象的请求时它不起作用!

错误信息是:

{
    "timestamp": 1516897619316,
    "status": 400,
    "error": "Bad Request",
    "exception": "org.springframework.http.converter.HttpMessageNotReadableException",
    "message": "JSON parse error: Can not construct instance of io.starter.topic.Topic: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of io.starter.topic.Topic: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)\n at [Source: java.io.PushbackInputStream@1ff3f09a; line: 2, column: 9]",
    "path": "/topics/"
}

我的实体:

public class Topic {
    private String id;
    private String name;
    private String author;
    private String desc;

    public Topic(String id, String name, String author, String desc) {

        this.id = id;
        this.name = name;
        this.author = author;
        this.desc = desc;
    }
    //getters and setters

我的控制器:

public class TopicController {

    @Autowired
    private TopicService topicService;


    @RequestMapping(value = "/topics", method = RequestMethod.POST)
    public void addTopic(@RequestBody Topic topic) {
        topicService.addTopic(topic);
    }

我的服务:

@Service
public class TopicService {
    private List<Topic> topics = new ArrayList<>(Arrays.asList(
            new Topic("1", "topic1", "Martin", "T1"),
            new Topic("2", "topic2", "Jessie", "T2")  
            ));



    public void addTopic(Topic topic) {

        topics.add(topic);
    }

}

我的 json:

{
    "id": "3",
    "name": "topic3",
    "author": "Jessie3",
    "desc": "T3"
}

请帮忙!

【问题讨论】:

    标签: java spring-boot


    【解决方案1】:

    为了反序列化,Topic 必须有一个零参数的构造函数。

    例如:

    public class Topic {
        private String id;
        private String name;
        private String author;
        private String desc;
    
        // for deserialisation
        public Topic() {}    
    
        public Topic(String id, String name, String author, String desc) {    
            this.id = id;
            this.name = name;
            this.author = author;
            this.desc = desc;
        }
    
        // getters and setters
    
    }     
    

    这是Jackson 库的默认行为。

    【讨论】:

    • 谢谢!我已经解决了这个问题!
    • 提供你所做的解决方案。
    • 大多数情况下,原因是,没有此答案中所述的默认无参数构造函数。
    • 如果 FirstClass 具有 secondClass 作为属性,这个答案是最好的,与下面的 Andreas 一起。 FirstClass 在构造函数上应该有一个 JsonCreator 注释,该构造函数将第二个对象(或 List)作为 JsonProperty 注释的参数。第二个 Class 需要有一个空的构造函数,其中包含所有属性的 getter 和 setter。
    • 谢谢。这解决了我的问题。 :)
    【解决方案2】:

    你需要用@JsonCreator注解构造函数:

    可用于将构造函数和工厂方法定义为用于实例化关联类的新实例的标记注释。

    注意:注释创建者方法(构造函数、工厂方法)时,方法必须是:

    • 没有JsonProperty参数注释的单参数构造函数/工厂方法:如果是这样,这就是所谓的“委托创建者”,在这种情况下,杰克逊首先将JSON绑定到参数类型,然后调用创建者。这通常与JsonValue(用于序列化)结合使用。
    • 构造函数/工厂方法,其中每个参数都使用JsonPropertyJacksonInject进行注释,以指示要绑定到的属性名称

    另请注意,所有JsonProperty 注释必须指定实际名称(“默认”不是空字符串),除非您使用可以检测参数名称的扩展模块之一;这是因为 8 之前的默认 JDK 版本无法从字节码存储和/或检索参数名称。但是对于 JDK 8(或使用辅助库,如 Paranamer,或其他 JVM 语言,如 Scala 或 Kotlin),指定名称是可选的。

    像这样:

    @JsonCreator
    public Topic(@JsonProperty("id") String id, @JsonProperty("name") String name,
                 @JsonProperty("author") String author, @JsonProperty("desc") String desc) {
        this.id = id;
        this.name = name;
        this.author = author;
        this.desc = desc;
    }
    

    【讨论】:

      猜你喜欢
      • 2018-01-17
      • 2019-04-01
      • 2021-10-06
      • 2020-06-14
      • 1970-01-01
      • 2019-06-28
      • 1970-01-01
      • 2020-04-13
      • 2020-12-10
      相关资源
      最近更新 更多