Java JSON 解析错误:无法构造 io.starter.topic.Topic 的实例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/48448079/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JSON parse error: Can not construct instance of io.starter.topic.Topic
提问by hackerang
Im learning Spring Boot and I made a demo but when I POST a request to add a Object it didn't work!
我正在学习 Spring Boot 并做了一个演示,但是当我发布添加对象的请求时,它不起作用!
The error message is:
错误信息是:
{
"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.Hymanson.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/"
}
My Entity:
我的实体:
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 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
My controller:
我的控制器:
public class TopicController {
@Autowired
private TopicService topicService;
@RequestMapping(value = "/topics", method = RequestMethod.POST)
public void addTopic(@RequestBody Topic topic) {
topicService.addTopic(topic);
}
public class TopicController {
@Autowired
private TopicService topicService;
@RequestMapping(value = "/topics", method = RequestMethod.POST)
public void addTopic(@RequestBody Topic topic) {
topicService.addTopic(topic);
}
My service:
我的服务:
@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);
}
}
@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);
}
}
My json:
我的json:
{
"id": "3",
"name": "topic3",
"author": "Jessie3",
"desc": "T3"
}
Please Help !
请帮忙 !
回答by glytching
For deserialisation purposes Topic
must have a zero-arg constructor.
出于反序列化的目的,Topic
必须有一个零参数构造函数。
For example:
例如:
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
}
This is the default behaviour of the Hymansonlibrary.
这是Hymanson库的默认行为。
回答by Andreas
You need to annotate the constructor with @JsonCreator
:
您需要使用以下内容注释构造函数@JsonCreator
:
Marker annotation that can be used to define constructors and factory methods as one to use for instantiating new instances of the associated class.
NOTE: when annotating creator methods (constructors, factory methods), method must either be:
- Single-argument constructor/factory method without
JsonProperty
annotation for the argument: if so, this is so-called "delegate creator", in which case Hymanson first binds JSON into type of the argument, and then calls creator. This is often used in conjunction withJsonValue
(used for serialization).- Constructor/factory method where every argumentis annotated with either
JsonProperty
orHymansonInject
, to indicate name of property to bind toAlso note that all
JsonProperty
annotations must specify actual name (NOT empty String for "default") unless you use one of extension modules that can detect parameter name; this because default JDK versions before 8 have not been able to store and/or retrieve parameter names from bytecode. But with JDK 8 (or using helper libraries such as Paranamer, or other JVM languages like Scala or Kotlin), specifying name is optional.
可用于将构造函数和工厂方法定义为用于实例化关联类的新实例的标记注释。
注意:在注释创建者方法(构造函数、工厂方法)时,方法必须是:
- 不带
JsonProperty
参数注解的单参数构造函数/工厂方法:如果是这样,这就是所谓的“委托创建者”,在这种情况下,Hymanson 首先将 JSON 绑定到参数的类型,然后调用creator。这通常与JsonValue
(用于序列化)结合使用。- 构造函数/工厂方法,其中每个参数都用
JsonProperty
或注释HymansonInject
,以指示要绑定到的属性名称另请注意,
JsonProperty
除非您使用可以检测参数名称的扩展模块之一,否则所有注释都必须指定实际名称(“默认”不是空字符串);这是因为 8 之前的默认 JDK 版本无法从字节码中存储和/或检索参数名称。但是对于 JDK 8(或使用辅助库,如 Paranamer,或其他 JVM 语言,如 Scala 或 Kotlin),指定名称是可选的。
Like this:
像这样:
@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;
}