programing

잭슨의 object Mapper를 사용하여 인터페이스 필드를 역직렬화하려면 어떻게 해야 합니까?

yellowcard 2023. 3. 26. 10:03
반응형

잭슨의 object Mapper를 사용하여 인터페이스 필드를 역직렬화하려면 어떻게 해야 합니까?

ObjectMapperreadValue(InputStream in, Class<T> valueType)함수에는 클래스가 필요합니다.단, 내부적으로 전달하고 있는 클래스가 데이터 멤버로서 인터페이스를 가지고 있는 경우는, 어떻게 하면 좋을까요.

이 예외의 이면에 있는 이유는 이해할 수 있습니다만, Jackson이 합격 클래스의 내부 인터페이스의 구체적인 클래스를 취득하고 있지 않기 때문에, 제 질문은 어떻게 그것을 해결할 것인가 하는 것입니다.그럼 어떻게 역직렬화하죠?역직렬화하려는 클래스는 다음과 같습니다.

class BaseMetricImpl<N> implements Metric<N> {
    protected MetricValueDescriptor descriptor;
}

여기서MetricValueDescriptor는 인터페이스이기 때문에, 다음의 에러가 발생합니다.

com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of MetricValueDescriptor, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information
 at [Source: java.io.ByteArrayInputStream@2ede2c9f; line: 1, column: 2] (through reference chain: SingleValueMetricImpl["descriptor"])
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
    at com.fasterxml.jackson.databind.DeserializationContext.instantiationException(DeserializationContext.java:624)
    at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:115)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:375)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:98)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:308)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2793)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1989)

Jackson은 분명히 이 빌딩을 건설할 수 없습니다.MetricValueDescriptor오브젝트는 인터페이스이기 때문에잭슨에게 오브젝트를 구성하는 방법을 알려주려면 json과 Object Mapper에 추가 정보가 필요합니다.여기 한 가지 방법이 있습니다.MVDImpl실장하는 구체적인 클래스입니다.MetricValueDescriptor:

Jackson 자체에 있는 필드를 통해 필요한 유형 정보를 알려줄 수 있습니다."type"이를 위해서는 인터페이스에서 및 주석을 사용해야 합니다.예를들면,

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "type")
@JsonSubTypes({
    @Type(value = MVDImpl.class, name = "mvdimpl") })
interface MetricValueDescriptor
{
   ...
}

를 추가해야 합니다."type":"mvdimpl"json에도 입력해 주세요.

더 많은 정보를 얻기 위해 공식 문서를 참조하려고 했는데, 이 주제를 다루는 훌륭한 블로그를 발견했습니다. - 잭슨과 JSON의 역직렬화(Deserialize JSON with Jackson.이 토픽은 꽤 포괄적이고 예를 들어 설명하고 있습니다.따라서 커스터마이즈가 더 필요한 경우 반드시 읽어보시기 바랍니다.

두 가지 방법 중 하나를 사용할 수 있지만 둘 다 인터페이스를 구현하는 구체적인 클래스를 수동으로 만들어야 합니다.

  1. @Hari Menon의 답변과 사용@JsonSubTypes이것은 타입 필드나 다른 것을 도입해, 사용하는 실장을 트리거 할 수 있는 경우에 유효합니다.
  2. 사용하다@JsonDeserialize기본적으로 사용되는 콘크리트 클래스를 잭슨에게 알려줍니다.
@JsonDeserialize(as = MVDImpl.class)
interface MetricValueDescriptor
{
   ...
}

자세한 설명을 드리겠습니다.https://zenidas.wordpress.com/recipes/jackson-deserialization-of-interfaces/

그리고 문서: https://fasterxml.github.io/jackson-databind/javadoc/2.8/com/fasterxml/jackson/databind/annotation/JsonDeserialize.html

코드를 변경할 필요가 없습니다.매퍼에서 프로그래밍 방식으로 설정할 수 있습니다.

static setup() {
   final var simpleModule = new SimpleModule()
        .addAbstractTypeMapping(<Interface>.class, <Implementation>.class);

   objMapper = new ObjectMapper()
        .registerModule(new Jdk8Module()) // You probably want this as well
        .registerModule(simpleModule);
}

언급URL : https://stackoverflow.com/questions/19379863/how-to-deserialize-interface-fields-using-jacksons-objectmapper

반응형