programing

기본 구성과 같은 작성자가 없습니다. 개체 값에서 직렬화할 수 없습니다(위임자 또는 속성 기반 작성자 없음).

powerit 2023. 9. 5. 20:50
반응형

기본 구성과 같은 작성자가 없습니다. 개체 값에서 직렬화할 수 없습니다(위임자 또는 속성 기반 작성자 없음).

저는 Retrofit과 Jackson을 사용하여 역직렬화하는 API를 사용하려고 합니다.onFailure 오류가 발생합니다.No Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator.

이유: 이 오류는 잭슨 라이브러리가 빈 생성자가 없는 모델을 만드는 방법을 알지 못하고 모델에 매개 변수에 주석을 달지 않은 생성자가 포함되어 있기 때문에 발생합니다.@JsonProperty("field_name")기본적으로 생성자를 클래스에 추가하지 않은 경우 Java 컴파일러는 빈 생성자를 만듭니다.

솔루션:빈 생성자를 모델에 추가하거나 생성자 매개변수에 주석을 추가합니다.@JsonProperty("field_name")

Kotlin 데이터 클래스를 사용하는 경우 다음을 사용하여 주석을 달 수도 있습니다.@JsonProperty("field_name")또는 Jackson 모듈 kotlin을 등록합니다.ObjectMapper.

http://www.jsonschema2pojo.org/ 을 사용하여 모델을 만들 수 있습니다.

나는 이 오류를 찾으러 여기에 왔습니다.

No Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator

Retrofit과 관련이 없지만 Jackson을 사용하는 경우 클래스에 기본 생성자를 추가하여 오류를 해결했습니다.더 많은 정보: https://www.baeldung.com/jackson-exception

위 링크에서 가장 관련성이 높은 비트:

"이 예외는 Jackson이 생성자에 액세스할 수 없는 경우 발생합니다.가 JSON 할 때, JSON 문자하직때할고려화렬,JsonMappingException: No Suitable Constructor Found 생성자를 하면 됩니다.

    public Foo() {
        super();
    }

이제 역직렬화하면 프로세스가 제대로 작동할 것입니다."

POJO 모델에서 Lombok을 사용하는 경우 다음 주석이 있어야 합니다.

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor

수 , 다할수있만지시,▁sure.@Getter그리고 특히.

은 야합다니해를 사용해야 .jackson-module-kotlin데이터 클래스로 역직렬화합니다.자세한 내용은 여기를 참조하십시오.

되지 않은 클래스가입니다.ObjectMapper그것은 그것을 가지고 있지 않습니다.KotlinModule 코드를 합니다.다음 코드를 예로 들어 보겠습니다.

data class TestDataClass (val foo: String)

val jsonString = """{ "foo": "bar" }"""
val deserializedValue = ObjectMapper().readerFor(TestDataClass::class.java).readValue<TestDataClass>(jsonString)

이 작업은 다음 오류와 함께 실패합니다.

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `test.SerializationTests$TestDataClass` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)

의 하고 를 대체하면,ObjectMapper와 함께jacksonObjectMapper(단순정반을함환상히)를 반환함)ObjectMapperKotlinModule등록됨), 작동합니다. 즉.

val deserializedValue = jacksonObjectMapper().readerFor(TestDataClass::class.java).readValue<TestDataClass>(jsonString)

잘 할 것 .jacksonObjectMapper역직렬화를 수행합니다.

쿼커스, 잭슨, 롬복.그래서 저는 이 문제를 추가하여 해결했습니다.@Jacksonized모델 클래스의 속성입니다.모든 속성은 다음과 같습니다.

@Jacksonized //missing
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ...

이것이 오래된 게시물이라는 것을 알지만, Retrofit을 사용하는 사람이라면 누구에게나 유용할 수 있습니다.

Retrofit + Jackson + Kotlin + Data 클래스를 사용하는 경우 다음이 필요합니다.

  1. 더하다implement group: 'com.fasterxml.jackson.module', name: 'jackson-module-kotlin', version: '2.7.1-2' 수 종속성에 합니다.
  2. Retrofit을 작성할 때 Kotlin Jackson Mapper를 전달하여 Retrofit이 올바른 Mapper를 사용하도록 합니다. 예:
    val jsonMapper = com.fasterxml.jackson.module.kotlin.jacksonObjectMapper()

    val retrofit = Retrofit.Builder()
          ...
          .addConverterFactory(JacksonConverterFactory.create(jsonMapper))
          .build()

참고: Retrofit을 사용하지 않을 경우, @Jayson Minard는 보다 일반적인 접근 방식을 사용합니다.

저는 비슷한 문제(잭슨, 롬복, 그라들 사용)와 args 생성자가 없는 POJO를 가지고 있었습니다. 해결책은 추가하는 것이었습니다.

lombok.anyConstructor.addConstructorProperties=true

lombok.config 파일로

no 인수 생성자를 추가하여 이 문제를 해결했습니다.롬복을 사용하는 경우에는 추가만 하면 됩니다.@NoArgsConstructor주석:

@AllArgsConstructor
@NoArgsConstructor
@Getter
@ToString
@EqualsAndHashCode
public class User {
    private Long userId;
    private String shortName;
}

롬복을 사용하고 있습니다.입력하지 않아서 오류가 발생했습니다.@NoArgsConstructor내 모범반에서.

사용하는 경우lombok사용할 수 있습니다.@Jacksonized 주석

세터가 필요하지 않습니다. 이 주석은 사용할 수 있습니다.@Value.

필없습다가 필요 없습니다.@NoArgsConstructor사용할 수 있습니다.@Builder아니면 그냥@RequiredArgsConstructor.

코틀린과 함께 구조를 사용하고 있으며 @ConstructorProperties를 사용하여 해결했습니다.

    data class MyResponse @ConstructorProperties("message", "count") constructor(
        val message: String,
        val count: Int
    )

잭슨은 @ConstructorProperties를 사용합니다.이것은 Lombok@Data도 수정할 것입니다.

오류가 언급했듯이 클래스에는 기본 생성자가 없습니다.

엔티티 클래스에 @NoArgsConstructor를 추가하면 이 문제가 해결됩니다.

추가하기만 하면 됩니다.@NoArgsConstructor그리고 그것은 동작한다.

Yoni Gibbs의 답변을 확장하면, 만약 당신이 개조를 사용하고 Jackson과 직렬화를 구성하는 안드로이드 프로젝트에 있다면, 당신은 kotlin의 데이터 클래스에서 예상대로 역직렬화 작업을 수행할 수 있습니다.

빌드 그라들 가져오기에서 다음을 수행합니다.

implementation "com.fasterxml.jackson.module:jackson-module-kotlin:2.11.+"

그런 다음, 개조 작업을 수행합니다.

val serverURL = "http://localhost:8080/api/v1"

val objectMapper = ObjectMapper()
objectMapper.registerModule(KotlinModule())
//Only if you are using Java 8's Time API too, require jackson-datatype-jsr310
objectMapper.registerModule(JavaTimeModule())

Retrofit.Builder()
    .baseUrl(serverURL)
    .client(
        OkHttpClient.Builder()
           .readTimeout(1, TimeUnit.MINUTES)//No mandatory
            .connectTimeout(1, TimeUnit.MINUTES)//No mandatory
            .addInterceptor(UnauthorizedHandler())//No mandatory
            .build())
    .addConverterFactory(
                JacksonConverterFactory.create(objectMapper)
            )
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .build()

데이터 클래스:

@JsonIgnoreProperties(ignoreUnknown = true)
data class Task(val id: Int,
                val name: String,
                @JsonSerialize(using = LocalDateTimeSerializer::class)
                @JsonDeserialize(using = LocalDateTimeDeserializer::class)
                val specificDate: LocalDateTime?,
                var completed: Boolean,
                val archived: Boolean,
                val taskListId: UUID?

벡의 대답은 정확합니다.

그러나 누군가가 rest controller에서 불변 클래스를 사용하려고 하는 경우, 즉 롬복의 클래스를 사용하는 경우.@value 그면추야합니다해가러를 추가해야 .lombok.anyConstructor.addConstructorProperties=true

이름이 지정된 파일을 만들 수 있습니다.lombok.config pom에서 이 "pom.xml"에합니다.

https://stackoverflow.com/a/56022839/6700081

기본 구조가 없는 클래스의 경우, 예를 들어 불변 객체로 작업할 때 Jackson은 기본적으로 객체에 JSON을 역직렬화할 수 없습니다.다음과 같은 주석을 사용하여 이 문제를 해결할 수 있습니다.@JsonCreator잭슨이 주어진 JSON을 역직렬화하는 방법을 알 수 있도록 도와줄 수 있습니다.

샘플 코드는 다음과 같습니다.

package com.test.hello;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class Payment {

    private final Card card;

    private final Amount amount;

    @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
    public Payment(@JsonProperty("card") Card card, @JsonProperty("amount") Amount amount) {
       this.card = card;
       this.amount = amount;
    }

    public Card getCard() {
       return card;
    }

    public Amount getAmount() {
        return amount;
    }
}

저는 이 문제가 있었고 아래 코드로 수정했습니다.

@Configuration
open class JacksonMapper {

    @Bean
    open fun mapper(): ObjectMapper {
        val mapper = ObjectMapper()
        ...

        mapper.registerModule(KotlinModule())
        return mapper
    }
}

저도 같은 오류가 발생하여 파라미터가 없는 생성자를 추가한 후 문제가 해결되었습니다.

enter image description here

롬복, 특히 @Builder에 주의하세요.

나에게 그 문제를 해결한 것은:

   @JsonDeserialize(builder = X.XBuilder.class)
       class X{
          @JsonPOJOBuilder(withPrefix = "")
          public static class XBuilder{

          }
}

당신의 삶이 더 편해지길 바랍니다.

@NoArgsConstructor그것은 문제를 해결할 것입니다. 우리가 제공하지 추가할 것이기 입니다.NoArgsConstructor우리는 이 예외를 받을 것입니다.기본 생성자를 강제로 추가해야 합니다.

대답이 더 나은 설명을 제공한다는 것을 지적하고 싶습니다.
기본적으로 당신은 둘 중 하나를 가질 수 있습니다.@Getter그리고.@NoArgConstructor
아니면 롬복이 재생산하도록 내버려 둬라.@ConstructorProperties용사를 lombok.config 데이터베이스,
의 자바 를 또는당프자컴파다니합일를로트로 하세요.-parameters 깃발, 깃발,
아니면 잭슨이 롬복의 것을 사용하도록 내버려 둬.@Builder

만약 당신이 LOMBOK를 사용하고 있다면.lombok.config 파일이 없으면 파일을 만들고 이 줄을 추가합니다.

lombok.anyconstructor.addconstructorproperties=true

클래스에 생성자 추가 또는 pojo를 사용하는 경우 @NoArgsConstructor @AllArgsConstructor 추가

- Json Property 함포 -도 합니다.@JsonProperty("name") private List<Employee> name;

Unirest를 http 라이브러리로 사용하는 경우,GsonObjectMapper JacksonObjectMapper또한 작동할 것입니다.

<!-- https://mvnrepository.com/artifact/com.konghq/unirest-object-mappers-gson -->
<dependency>
    <groupId>com.konghq</groupId>
    <artifactId>unirest-object-mappers-gson</artifactId>
    <version>2.3.17</version>
</dependency>
Unirest.config().objectMapper = GsonObjectMapper()

Lombok builder를 사용할 때 위의 오류가 발생합니다.

 @JsonDeserialize(builder = StationResponse.StationResponseBuilder.class)
 public class StationResponse{
   //define required properties 
 }     

 @JsonIgnoreProperties(ignoreUnknown = true)
 @JsonPOJOBuilder(withPrefix = "")
 public static class StationResponseBuilder {}

참조: https://projectlombok.org/features/Builder With Jackson

으로 이 문제를 할 수 .@JacksonProperty다음과 같이 사용할있습니다.

import com.fasterxml.jackson.annotation.JsonProperty
...
data class Station(
     @JacksonProperty("repsol_id") val repsol_id: String,
     @JacksonProperty("name") val name: String,
...

제 문제의 원인은 매우 드문 것 같습니다. 다른 사람이 동일한 조건에서 오류를 얻는지 확실하지 않습니다. 이전의 커밋을 다르게 하여 원인을 찾았습니다. 여기 있습니다.

내 build.gradle을 통해 나는 이 두 가지 컴파일러 옵션을 사용하고 있었고, 이 줄에 주석을 달아 문제를 해결했습니다.

//compileJava.options.compilerArgs = ['-Xlint:unchecked','-Xlint:deprecation']

아래 사용 사례에서 동일한 오류가 발생했습니다.

각각의 빈에 기본 생성자가 없는 상태에서 스프린트 부트(2.0.0 스냅샷 버전)를 사용하여 나머지(Put mapping) 끝점을 맞추려고 했습니다.

그러나 최신 Spring Boot 버전(2.4.1 버전)에서는 동일한 코드가 오류 없이 작동합니다.

따라서 최신 버전의 Spring Boot에서는 기본 생성자가 더 이상 필요하지 않습니다.

같은 오류가 발생했는데 제 모델Serializable을 구현하지 않은 것이 문제였으니 이것도 한 가지 이유이므로 확인해 보십시오.

저는 코틀린에서도 예외에 직면했습니다.KotlinModule을 적용한 후에도 여전히 문제가 발생하면 (아마도) 어딘가에 가치 클래스가 있을 수 있습니다.

언급URL : https://stackoverflow.com/questions/53191468/no-creators-like-default-construct-exist-cannot-deserialize-from-object-valu

반응형