@AllArgsConstructor
@RestController
@RequestMapping("/api/subject")
public class SubjectController {
private SubjectService subjectService;
@PostMapping
public void createSubject(@RequestBody SubjectCreationDTO subjectCreationDTO) {
LoggingController.getLogger().info(subjectCreationDTO.getTitle());
// subjectService.createSubject(subjectCreationDTO);
}
}
和subjectCreationdto:
@AllArgsConstructor
@Getter
@Setter
public class SubjectCreationDTO {
private String title;
}
因此,我在提出发布请求时会遇到此错误:
JSON分析错误:无法构建
pweb.examhelper.dto.subject.SubjectCreationDTO
(虽然至少 一个创造者存在):无法从对象值中估算(否 委托或基于财产的创建者)”来解决此错误,但是为什么在其他情况下,我的情况几乎完全相同。i可以通过将@noargsconstructor添加到
SubjectCreationDTO
@PostMapping
public ResponseEntity<StudentDTO> createStudent(@RequestBody StudentCreationDTO studentCreationDTO) {
StudentDTO savedStudent = studentService.createStudent(studentCreationDTO);
return new ResponseEntity<>(savedStudent, HttpStatus.CREATED);
}
StudentCreationDTO
类:
@AllArgsConstructor
@Getter
@Setter
public class StudentCreationDTO {
private String username;
private String firstName;
private String lastName;
private String email;
}
在杰克逊(Jackson)的命令中,它需要一个JSON,它需要默认的构造函数或用
@JsonCreator
InvalidDefinitionException
。这是从对象值(没有委托或基于属性的创建者)
试图说的错误之词。在一个默认的构造函数的情况下,杰克逊首先创建了类的默认实例,然后将每个JSON字段注入对象中。 类似,杰克逊(Jackson)首先使用
@JsonCreator
用方法来实例化对象,仅用用@JsonCreator
注释的方法的参数实例化对象。然后,将每个剩余字段从JSON设置为对象。注释方法可以是参数化的构造函数或静态方法。
通常,您应该只用一个@AllArgsContructor
进行对象的序列化,但是必须有其他配置为您处理参数化的实例化。这也是来自
Baeldung的文章,其中10.1点显示了一个典型的班级,即没有被判决,因为它既缺乏默认的构造函数或用
@JsonCreator
。
我还附加了一个示例,您可以在核编译器中尝试显示杰克逊在只有一个参数化的构造函数而没有默认构造函数或
@JsonCreator
方法时的行为。确切地说,该示例处理以下方案:
StudentCreationDTO1
不值得启动,因为它仅提供@AllArgsConstructor
且不提供默认构造函数。实际上,扔了一个InvalidDefinitionException
。
StudentCreationDTO2
StudentCreationDTO3
值得注意,因为它提供了用@JsonCreator
注释的(构造函数)方法。注释不需要包括所有类的字段。杰克逊只有几个就足以创建一个StudentCreationDTO3
public class Main {
public static void main(String[] args) throws JsonProcessingException {
String json = "{\n" +
"\t\"username\": \"johndoe\",\n" +
"\t\"firstName\": \"john\",\n" +
"\t\"lastName\": \"doe\",\n" +
"\t\"email\": \"[email protected]\"\n" +
"}";
ObjectMapper objectMapper = new ObjectMapper();
// Deserializing with no default constructor
try {
StudentCreationDTO1 studentCreationDTO1 = objectMapper.readValue(json, StudentCreationDTO1.class);
System.out.println(studentCreationDTO1);
} catch (InvalidDefinitionException e) {
System.out.println("Throwing InvalidDefinitionException because there is no default constructor or method marked with @JsonCreator");
}
// Deserializing with default constructor
try {
StudentCreationDTO2 studentCreationDTO2 = objectMapper.readValue(json, StudentCreationDTO2.class);
System.out.println("\n" + studentCreationDTO2);
} catch (InvalidDefinitionException e) {
System.out.println("Throwing InvalidDefinitionException because there is no default constructor or method marked with @JsonCreator");
}
// Deserializing with no default constructor but with method annotated with @JsonCreator
try {
StudentCreationDTO3 studentCreationDTO3 = objectMapper.readValue(json, StudentCreationDTO3.class);
System.out.println("\n" + studentCreationDTO3);
} catch (InvalidDefinitionException e) {
System.out.println("Throwing InvalidDefinitionException because there is no default constructor or method marked with @JsonCreator");
}
}
}
@Data
@AllArgsConstructor
public class StudentCreationDTO1 {
private String username;
private String firstName;
private String lastName;
private String email;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class StudentCreationDTO2 {
private String username;
private String firstName;
private String lastName;
private String email;
}
@Data
public class StudentCreationDTO3 {
private String username;
private String firstName;
private String lastName;
private String email;
@JsonCreator
public StudentCreationDTO3(@JsonProperty("username") String username, @JsonProperty("firstName") String firstName) {
this.username = username;
this.firstName = firstName;
}
}
further关于杰克逊deserializtion的注释
的一篇很棒的文章,该文章涉及以下所有序列化和挑选序列化的情况。
如果属性有一个设置器,则通过相应的setter方法设置其值。public class MyBean {
private String name;
//... default constructor ....
//... standard getName() ...
// Jackson uses the corresponding setter to set the property name
public void setName(String name) {
this.name = name;
}
}
如果没有提供设置器,但是类展示了用@JsonSetter
public class MyBean {
private String name;
//... default constructor ....
//... standard getName() ...
// Marking the method with @JsonSetter(value = "name")
// because the JSON contains a property called 'name',
// but Jackson cannot find any setter in the form of setName(String)
@JsonSetter(value = "name")
public void setTheName(String name) {
this.name = name;
}
}
如果没有提供设置器或@JsonSetter
方法,并且类仅显示Getter方法,那么Jackson会回到反射以设置对象的属性。
public class MyBean {
private String name;
//... default constructor ....
// Jackson cannot set a value with just a getter,
// so it falls back on reflection to set 'name'
public void getName() {
return name;
}
}
ObjectMapper.setVisibility()
。
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
...
public class MyBean {
// Every field is set by Jackson due to Visibility.ANY
public String name;
proteced int id;
float value;
private boolean flag;
//... default constructor ....
//... No getters or setters ....
}