JsonMappingException : [단순 유형, 클래스] 유형에 적합한 생성자가 없습니다. JSON 객체에서 인스턴스를 생성 할 수 없습니다.
JSON 요청을 가져 와서 처리하려고 할 때 다음 오류가 발생합니다.
org.codehaus.jackson.map.JsonMappingException : [단순 유형, 클래스 com.myweb.ApplesDO] 유형에 적합한 생성자를 찾을 수 없습니다 : JSON 객체에서 인스턴스를 생성 할 수 없습니다 (유형 정보를 추가 / 활성화해야합니까?).
보내려는 JSON은 다음과 같습니다.
{
"applesDO" : [
{
"apple" : "Green Apple"
},
{
"apple" : "Red Apple"
}
]
}
컨트롤러에는 다음과 같은 메소드 서명이 있습니다.
@RequestMapping("showApples.do")
public String getApples(@RequestBody final AllApplesDO applesRequest){
// Method Code
}
AllApplesDO는 ApplesDO의 래퍼입니다.
public class AllApplesDO {
private List<ApplesDO> applesDO;
public List<ApplesDO> getApplesDO() {
return applesDO;
}
public void setApplesDO(List<ApplesDO> applesDO) {
this.applesDO = applesDO;
}
}
ApplesDO :
public class ApplesDO {
private String apple;
public String getApple() {
return apple;
}
public void setApple(String appl) {
this.apple = apple;
}
public ApplesDO(CustomType custom){
//constructor Code
}
}
Jackson이 JSON을 하위 클래스의 Java 객체로 변환 할 수 없다고 생각합니다. Jackson이 JSON을 Java 오브젝트로 변환하는 구성 매개 변수에 도움을주십시오. Spring Framework를 사용하고 있습니다.
편집 : 위의 샘플 클래스 에서이 문제를 일으키는 주요 버그가 포함되었습니다-해결책에 대한 대답을 찾으십시오.
그래서 마침내 문제가 무엇인지 깨달았습니다. 내가 의심 한 것처럼 Jackson 구성 문제는 아닙니다.
실제로 문제는 ApplesDO 클래스 에 있었습니다 .
public class ApplesDO {
private String apple;
public String getApple() {
return apple;
}
public void setApple(String apple) {
this.apple = apple;
}
public ApplesDO(CustomType custom) {
//constructor Code
}
}
클래스에 대해 사용자 정의 생성자가 정의되어 기본 생성자가되었습니다. 더미 생성자를 소개하면 오류가 사라졌습니다.
public class ApplesDO {
private String apple;
public String getApple() {
return apple;
}
public void setApple(String apple) {
this.apple = apple;
}
public ApplesDO(CustomType custom) {
//constructor Code
}
//Introducing the dummy constructor
public ApplesDO() {
}
}
이것은 다음과 같은 이유로 발생합니다.
당신의 내부 클래스는 정적 으로 정의되어야합니다
private static class Condition { //jackson specific }
클래스에 기본 생성자가 없을 수도 있습니다 ( 업데이트 : 그렇지 않은 것 같습니다)
private static class Condition { private Long id; public Condition() { } // Setters and Getters }
세터가 올바르게 정의되지 않았거나 표시되지 않을 수 있습니다 (예 : 개인 세터)
더미 생성자가 필요없는 다른 솔루션을 추가하고 싶습니다. 더미 생성자는 약간 혼란스럽고 혼란 스럽습니다. 안전한 생성자를 제공 할 수 있으며 생성자 인수에 주석을 달아 Jackson이 생성자 매개 변수와 필드 간의 매핑을 결정할 수 있도록합니다.
다음과 같이 작동합니다. 주석 안의 문자열은 필드 이름과 일치해야합니다.
import com.fasterxml.jackson.annotation.JsonProperty;
public class ApplesDO {
private String apple;
public String getApple() {
return apple;
}
public void setApple(String apple) {
this.apple = apple;
}
public ApplesDO(CustomType custom){
//constructor Code
}
public ApplesDO(@JsonProperty("apple")String apple) {
}
}
이 문제가 발생했을 때 DO로 사용하기 위해 내부 클래스를 사용하려고 시도한 결과였습니다. 내적 계급의 건설은 (사일런트) 엔 클로징 계급의 인스턴스가 필요했습니다. Jackson은 이용할 수 없었습니다.
이 경우 내부 클래스를 자체 .java 파일로 이동하면 문제가 해결되었습니다.
일반적 으로이 오류는 기본 생성자를 만들지 않기 때문에 발생하지만 제 경우에는 부모 클래스 내부에서 사용 된 객체 클래스로 인해 문제가 발생했습니다. 이것은 하루 종일 낭비되었습니다.
Thumb Rule : 매핑 클래스로 사용한 각 클래스에 대한 기본 생성자를 추가합니다. 이것을 놓치고 문제가 발생합니다!
기본 생성자를 추가하면 작동합니다.
이 구조를 시험해 주시겠습니까? 내가 올바른 것을 기억하면 다음과 같이 사용할 수 있습니다.
{
"applesRequest": {
"applesDO": [
{
"apple": "Green Apple"
},
{
"apple": "Red Apple"
}
]
}
}
둘째, 각 클래스에 기본 생성자를 추가하여 도움이 될 수도 있습니다.
생성자에 주석을 달기 시작하면 모든 필드에 주석을 달아야합니다.
내 Staff.name 필드는 JSON 문자열에서 "ANOTHER_NAME"에 매핑됩니다.
String jsonInString="{\"ANOTHER_NAME\":\"John\",\"age\":\"17\"}";
ObjectMapper mapper = new ObjectMapper();
Staff obj = mapper.readValue(jsonInString, Staff.class);
// print to screen
public static class Staff {
public String name;
public Integer age;
public Staff() {
}
//@JsonCreator - don't need this
public Staff(@JsonProperty("ANOTHER_NAME") String n,@JsonProperty("age") Integer a) {
name=n;age=a;
}
}
모델 클래스에서 더미 빈 생성자를 만들어야하므로 json을 매핑하는 동안 setter 메서드로 설정됩니다.
deserialization에 Jackson이 사용할 수있는 옵션을 알고 있어야합니다. Java에서는 메소드 인수 이름이 컴파일 된 코드에 없습니다. 그렇기 때문에 Jackson은 일반적으로 생성자를 사용하여 이미 설정된 모든 항목으로 잘 정의 된 객체를 만들 수 없습니다.
따라서 빈 생성자가 있고 세터도있는 경우 빈 생성자와 세터를 사용합니다. 세터가 없으면 어두운 마법 (반사)을 사용합니다.
Jackson과 함께 생성자를 사용하려면 @PiersyP에서 언급 한대로 주석을 사용해야합니다. 빌더 패턴을 사용할 수도 있습니다. 예외가 발생하면 행운을 빕니다. Jackson의 오류 처리는 시간이 많이 걸리므로 오류 메시지에서 그 횡설수설을 이해하기 어렵습니다.
마지막 출판물에 관해서는 Lombok 1.18. *를 사용하면 문제가 발생하는 것과 동일한 문제가있었습니다.
@Data는 기본적으로 @RequiredArgsConstructor (매개 변수가있는 생성자)를 포함하기 때문에 내 솔루션은 @NoArgsConstructor (매개 변수가없는 생성자)를 추가하는 것이 었습니다.
lombok 설명서 https://projectlombok.org/features/all
문제가 해결됩니다.
package example.counter;
import javax.validation.constraints.NotNull;
import lombok.Data;
@Data
@NoArgsConstructor
public class CounterRequest {
@NotNull
private final Integer int1;
@NotNull
private final Integer int2;
}
사용자 지정 Jackson Jackson Serializer / Deserializer도 실패하는 것이 문제가 될 수 있습니다. 귀하의 경우는 아니지만 언급 할 가치가 있습니다.
나는 같은 예외에 직면했으며 그 경우였습니다.
나에게 이것은 작동했지만 라이브러리를 업그레이드하면이 문제가 발생했습니다. 문제는 다음과 같은 수업을하고있었습니다.
package example.counter;
import javax.validation.constraints.NotNull;
import lombok.Data;
@Data
public class CounterRequest {
@NotNull
private final Integer int1;
@NotNull
private final Integer int2;
}
롬복 사용 :
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
</dependency>
다시 떨어지는
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
문제가 해결되었습니다. 왜 그런지 확실하지 않지만 나중에 문서화하고 싶었습니다.
'Programing' 카테고리의 다른 글
SDK 'iOS 10.0'의 제품 유형 'Application'에 코드 서명이 필요합니다-StickerPackExtension에는 개발 팀 오류가 필요합니다 (0) | 2020.02.20 |
---|---|
^ M을 무시하는 git-diff (0) | 2020.02.20 |
DB에 이미지 저장-예 또는 아니요? (0) | 2020.02.20 |
Windows 7에서 java_home을 설정하는 방법은 무엇입니까? (0) | 2020.02.20 |
쉘에서 변수로 파일을 읽는 방법은 무엇입니까? (0) | 2020.02.20 |