@JsonIdentityReference는 동일한 값을 인식하지 않습니다.

하오 청

Root중복 항목이 있는 개체 ( ) 를 직렬화하려고합니다 MyObject. 전체 객체를 저장하고 싶습니다. 저는을 사용 @JsonIdentityReference하고 있습니다. 이것은 꽤 잘 작동합니다.

그러나 다른 참조를 가진 동일한 객체가 있으면 de-deserializable 객체를 생성한다는 것을 알고 있습니다. 이 동작을 변경하기 위해 Jackson에 구성이 있는지 궁금합니다. 감사합니다!

@Value
@AllArgsConstructor
@NoArgsConstructor(force = true)
class Root {
    private List<MyObject> allObjects;
    private Map<String, MyObject> objectMap;
}

@Value
@AllArgsConstructor
@NoArgsConstructor(force = true)
@JsonIdentityReference
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
class MyObject {
    private String id;
    private int value;
}

public class Main {
    public static void main() throws JsonProcessingException {
        // Constructing equal objects
        val obj1 = new MyObject("a", 1);
        val obj2 = new MyObject("a", 1);
        assert obj1.equals(obj2);

        val root = new Root(
                Lists.newArrayList(obj1),
                ImmutableMap.of(
                        "lorem", obj2
                )
        );
        val objectMapper = new ObjectMapper();

        val json = objectMapper.writeValueAsString(root);
        // {"allObjects":[{"id":"a","value":1}],"objectMap":{"lorem":{"id":"a","value":1}}}
        // Note here both obj1 and obj2 are expanded.

        // Exception: Already had POJO for id 
        val deserialized = objectMapper.readValue(json, Root.class);
        assert root.equals(deserialized);
    }
}

Jackson 2.10을 사용하고 있습니다.

전체 스택 추적 :

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Already had POJO for id (java.lang.String) [[ObjectId: key=a, type=com.fasterxml.jackson.databind.deser.impl.PropertyBasedObjectIdGenerator, scope=java.lang.Object]] (through reference chain: Root["objectMap"]->java.util.LinkedHashMap["lorem"]->MyObject["id"])
    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:394)
    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:353)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1714)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:371)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithObjectId(BeanDeserializerBase.java:1257)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:157)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringKeyMap(MapDeserializer.java:527)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:364)
    at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:29)
    at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4202)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3205)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3173)
    at Main.main(Main.java:53)
Caused by: java.lang.IllegalStateException: Already had POJO for id (java.lang.String) [[ObjectId: key=a, type=com.fasterxml.jackson.databind.deser.impl.PropertyBasedObjectIdGenerator, scope=java.lang.Object]]
    at com.fasterxml.jackson.annotation.SimpleObjectIdResolver.bindItem(SimpleObjectIdResolver.java:24)
    at com.fasterxml.jackson.databind.deser.impl.ReadableObjectId.bindItem(ReadableObjectId.java:57)
    at com.fasterxml.jackson.databind.deser.impl.ObjectIdValueProperty.deserializeSetAndReturn(ObjectIdValueProperty.java:101)
    at com.fasterxml.jackson.databind.deser.impl.ObjectIdValueProperty.deserializeAndSet(ObjectIdValueProperty.java:83)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:369)
    ... 14 more
sfiss

앞서 언급했듯이이 설정 obj1 == obj2은 동일한 ID를 가진 두 개체가 동일해야하기 때문에 인 경우에만 작동합니다 . 이 경우 두 번째 개체도 직렬화 중에 alwaysAsId = false확장됩니다 (첫 번째 개체 만 확장 됨).

그러나이 설정을 원하고 직렬화에 문제가없는 경우 키당 단일 인스턴스를 저장하는 역 직렬화를 위해 사용자 지정 Resolver를 사용할 수 있습니다.

@JsonIdentityReference(alwaysAsId = false)
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", resolver = CustomScopeResolver.class)
static class MyObject {

    private String id;
    // ...
}

class CustomScopeResolver implements ObjectIdResolver {

    Map<String, MyObject> data = new HashMap<>();

    @Override
    public void bindItem(final IdKey id, final Object pojo) {
        data.put(id.key.toString(), (MyObject) pojo);
    }

    @Override
    public Object resolveId(final IdKey id) {
        return data.get(id.key);
    }

    @Override
    public ObjectIdResolver newForDeserialization(final Object context) {
        return new CustomScopeResolver();
    }

    @Override
    public boolean canUseFor(final ObjectIdResolver resolverType) {
        return false;
    }

}

새 편집 : 분명히, 매우 쉽습니다. objectMapper.configure(SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID, true);DefaultSerializerProvider가 IdentityHashMap 대신 일반 Hashmap을 사용하여 직렬화 된 빈을 관리하도록 켜십시오 .

지원 중단됨 : 직렬화 업데이트 : 사용자 지정 SerializationProvider를 추가하여이를 수행 할 수 있습니다.

class CustomEqualObjectsSerializerProvider extends DefaultSerializerProvider {

    private final Collection<MyObject> data = new HashSet<>();
    private final SerializerProvider src;
    private final SerializationConfig config;
    private final SerializerFactory f;

    public CustomEqualObjectsSerializerProvider(
            final SerializerProvider src,
            final SerializationConfig config,
            final SerializerFactory f) {
        super(src, config, f);
        this.src = src;
        this.config = config;
        this.f = f;
    }

    @Override
    public DefaultSerializerProvider createInstance(final SerializationConfig config, final SerializerFactory jsf) {
        return new CustomEqualObjectsSerializerProvider(src, this.config, f);
    }

    @Override
    public WritableObjectId findObjectId(final Object forPojo, final ObjectIdGenerator<?> generatorType) {
        // check if there is an equivalent pojo, use it if exists
        final Optional<MyObject> equivalentObject = data.stream()
                .filter(forPojo::equals)
                .findFirst();

        if (equivalentObject.isPresent()) {
            return super.findObjectId(equivalentObject.get(), generatorType);
        } else {
            if (forPojo instanceof MyObject) {
                data.add((MyObject) forPojo);
            }
            return super.findObjectId(forPojo, generatorType);
        }

    }

}

@Test
public void main() throws IOException {
    // Constructing equal objects
    final MyObject obj1 = new MyObject();
    obj1.setId("a");

    final MyObject obj2 = new MyObject();
    obj2.setId("a");
    assert obj1.equals(obj2);

    final Root root = new Root();
    root.setAllObjects(Collections.singletonList(obj1));
    root.setObjectMap(Collections.singletonMap(
            "lorem", obj2));
    final ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setSerializerProvider(
            new CustomEqualObjectsSerializerProvider(
                    objectMapper.getSerializerProvider(),
                    objectMapper.getSerializationConfig(),
                    objectMapper.getSerializerFactory()));
    final String json = objectMapper.writeValueAsString(root);
    System.out.println(json); // second object is not expanded!
}

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

Hash :: make는 동일한 입력에 대해 동일한 값을 생성하지 않습니다.

분류에서Dev

중포 기지는 값을 설정하기위한 문자열 키를 인식하지 않습니다

분류에서Dev

Java : 값은 동일하지만 동일한 지 확인하는 if 문이 작동하지 않습니까?

분류에서Dev

VeeValidate는 동적 양식의 입력을 확인하지 않습니다.

분류에서Dev

Eclipse 색상 테마는 파일을 PHP로 인식하지 않습니다.

분류에서Dev

메서드는 리터럴 값으로 작동하지만 동일한 값을 보유하는 변수로는 작동하지 않습니다.

분류에서Dev

경고 : 조건부에서 포인터 유형이 일치하지 않습니다. 동일한 유형의 두 값을 사용하는 경우

분류에서Dev

Delphi와 MSVC는 동일한 방식으로 + NAN을 0과 비교하지 않습니다.

분류에서Dev

Ruby Date.parse 및 Javascript new Date ()는 동일한 형식을 허용하지 않습니다.

분류에서Dev

나는 행렬이 대칭인지 아닌지를 확인하는 프로그램을 코딩했습니다. 둘 다 정확 해 보이지만 한 가지 방식으로 작동하지만 다른 방식으로는 작동하지 않습니다.

분류에서Dev

strcmp는 '동일한'문자열에서 0을 반환하지 않습니다.

분류에서Dev

영숫자 문자열을 확인하는 정규식식이 작동하지 않습니다.

분류에서Dev

일반보기는 값을 반환하지 않습니다.

분류에서Dev

ListPreference는 선택한 값을 표시하지 않습니다.

분류에서Dev

사전은 특정 키에 값을 제공하지만 다른 키는 동일한 값을 얻습니다.

분류에서Dev

Pycharm 가져 오기는 동일한 모듈의 다른 파일을 인식하지 못합니다.

분류에서Dev

다른 일반 목록을받는 메서드는 호환되지 않는 형식으로 인해 작동하지 않습니다.

분류에서Dev

$ _POST는 PHP 게시물에서 작동하지 않습니다. ISSET은 이러한 값이 post 방식을 통해 인식되지 않았다고보고합니다.

분류에서Dev

Argparse는 유일한 위치 인수를 인식하지 않습니다.

분류에서Dev

Google 스프레드 시트 : 동일한 값은 동일한 것으로 인식되지 않습니다.

분류에서Dev

find는 동일한 필터와 일치하지 않는 파일을 찾습니다.

분류에서Dev

일부 값은 포함하지만 다른 값은 포함하지 않는 행을 계산할 수있는 OpenCalc에 대한 공식이 있습니까?

분류에서Dev

동일한 값을 제공하지 않는 TypeScript 및 멤버

분류에서Dev

동일한 값을 반환하지 않는 VLOOKUP

분류에서Dev

Model.listSubjectsWithProperty (Property p, String o)는 동일한 문자열 값을 가진 유형화 된 리터럴을 갖는 자원을 나열하지 않습니다.

분류에서Dev

strtoint는 동일한 값을 얻지 못합니다.

분류에서Dev

Typescript : 배열에 대한 함수 찾기가 작동하지만 if 문으로 값을 반환하는지 확인하면 작동하지 않습니다.

분류에서Dev

내 스위치가 작동하지 않는 이유를 알 수 없습니다. cin 입력을 인식하지 못하는 것 같습니다.

분류에서Dev

@JsonCreator는 Jackson을 사용하여 인식되지 않습니다.

Related 관련 기사

  1. 1

    Hash :: make는 동일한 입력에 대해 동일한 값을 생성하지 않습니다.

  2. 2

    중포 기지는 값을 설정하기위한 문자열 키를 인식하지 않습니다

  3. 3

    Java : 값은 동일하지만 동일한 지 확인하는 if 문이 작동하지 않습니까?

  4. 4

    VeeValidate는 동적 양식의 입력을 확인하지 않습니다.

  5. 5

    Eclipse 색상 테마는 파일을 PHP로 인식하지 않습니다.

  6. 6

    메서드는 리터럴 값으로 작동하지만 동일한 값을 보유하는 변수로는 작동하지 않습니다.

  7. 7

    경고 : 조건부에서 포인터 유형이 일치하지 않습니다. 동일한 유형의 두 값을 사용하는 경우

  8. 8

    Delphi와 MSVC는 동일한 방식으로 + NAN을 0과 비교하지 않습니다.

  9. 9

    Ruby Date.parse 및 Javascript new Date ()는 동일한 형식을 허용하지 않습니다.

  10. 10

    나는 행렬이 대칭인지 아닌지를 확인하는 프로그램을 코딩했습니다. 둘 다 정확 해 보이지만 한 가지 방식으로 작동하지만 다른 방식으로는 작동하지 않습니다.

  11. 11

    strcmp는 '동일한'문자열에서 0을 반환하지 않습니다.

  12. 12

    영숫자 문자열을 확인하는 정규식식이 작동하지 않습니다.

  13. 13

    일반보기는 값을 반환하지 않습니다.

  14. 14

    ListPreference는 선택한 값을 표시하지 않습니다.

  15. 15

    사전은 특정 키에 값을 제공하지만 다른 키는 동일한 값을 얻습니다.

  16. 16

    Pycharm 가져 오기는 동일한 모듈의 다른 파일을 인식하지 못합니다.

  17. 17

    다른 일반 목록을받는 메서드는 호환되지 않는 형식으로 인해 작동하지 않습니다.

  18. 18

    $ _POST는 PHP 게시물에서 작동하지 않습니다. ISSET은 이러한 값이 post 방식을 통해 인식되지 않았다고보고합니다.

  19. 19

    Argparse는 유일한 위치 인수를 인식하지 않습니다.

  20. 20

    Google 스프레드 시트 : 동일한 값은 동일한 것으로 인식되지 않습니다.

  21. 21

    find는 동일한 필터와 일치하지 않는 파일을 찾습니다.

  22. 22

    일부 값은 포함하지만 다른 값은 포함하지 않는 행을 계산할 수있는 OpenCalc에 대한 공식이 있습니까?

  23. 23

    동일한 값을 제공하지 않는 TypeScript 및 멤버

  24. 24

    동일한 값을 반환하지 않는 VLOOKUP

  25. 25

    Model.listSubjectsWithProperty (Property p, String o)는 동일한 문자열 값을 가진 유형화 된 리터럴을 갖는 자원을 나열하지 않습니다.

  26. 26

    strtoint는 동일한 값을 얻지 못합니다.

  27. 27

    Typescript : 배열에 대한 함수 찾기가 작동하지만 if 문으로 값을 반환하는지 확인하면 작동하지 않습니다.

  28. 28

    내 스위치가 작동하지 않는 이유를 알 수 없습니다. cin 입력을 인식하지 못하는 것 같습니다.

  29. 29

    @JsonCreator는 Jackson을 사용하여 인식되지 않습니다.

뜨겁다태그

보관