Jackson ContextualDeserializer не десериализует все поля - PullRequest
0 голосов
/ 07 июня 2018

Я внедряю специальный десериализатор Джексона для одной из моих сущностей.

Моя сущность выглядит следующим образом:

@Value
@JsonDeserialize
@AllArgsConstructor
public class TestModel {

    private final FieldUpdate<UUID> field1Update;
    private final FieldUpdate<UUID> field2Update;
    private final FieldUpdate<String> field3Update;

    public String toString() {
        return "TestModel. Field1="+(field1Update != null ? field1Update.toString() : null)+
                " Field2="+(field2Update != null ? field2Update.getClass().getName() : null) +
                " Field3="+(field3Update != null ? field3Update.getClass().getName() : null);
    }
}

Моя проблема в том, что сериализация работает, как и ожидалось - успешно сериализованныйОбъект выглядит следующим образом:

{
  "field1Update" : {
    "type" : "update",
    "value" : "f59c4ef9-52c4-4f3d-99e5-a33a13ae12f3"
  },
  "field2Update" : {
    "type" : "keep"
  },
  "field3Update" : {
    "type" : "reset"
  }
}

=> что правильно.(Есть 3 типа обновления, сохранения и сброса).Только для обновления требуется значение.

Проблема заключается в следующем: Когда я десериализую это, только первое поле (field1Update) будет десериализовано.Другие 2 поля (field2Update и field3Update) после завершения десериализации становятся пустыми.

Мой десериализатор выглядит следующим образом:

public class FieldUpdateDeserializer extends StdDeserializer implements ContextualDeserializer {

    private JavaType contentType;

    public FieldUpdateDeserializer(JavaType contentType) {
        this(null,contentType);
    }

    public FieldUpdateDeserializer() {
        this(null,null);
    }

    public FieldUpdateDeserializer(Class<?> vc, JavaType contentType) {
        super(vc);
        this.contentType = contentType;
    }

    public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
                                                BeanProperty property) throws JsonMappingException {
        JavaType t = property.getType();
        JavaType boundType = t.getBindings().getBoundType(0);
        return new FieldUpdateDeserializer(boundType);
    }

    @Override
    public Object deserialize(JsonParser jp, DeserializationContext ctx) throws IOException {
        if(!"type".equals(jp.nextFieldName()) )throw new JsonParseException(jp,"'type' expected");
        String typeVal = jp.nextTextValue();
        if("update".equals(typeVal)) {
            jp.nextValue(); //consume type.
            try {
                JsonDeserializer deser = ctx.findNonContextualValueDeserializer(contentType);
                return new Update<>(deser.deserialize(jp,ctx));
            } catch (Exception ex) {
                throw new IllegalStateException("Could not handle deserialization for type", ex);
            }
        } else if("keep".equals(typeVal)) {
            return new Keep<>();
        } else if("reset".equals(typeVal)) {
            return new Reset<>();
        } else {
            return ctx.handleUnexpectedToken(FieldUpdate.class, jp);
        }
    }
}

Интересный факт заключается в том, что Джексон вызывает десериализацию (...)метод только один раз, и я не могу понять, почему ....

Рад, если кто-то может дать мне подсказку.

привет, Майкл

1 Ответ

0 голосов
/ 08 июня 2018

Хорошо - после некоторого сна и анализа того, что происходит в сериализаторе Джексона, я обнаружил, что не использовал достаточно токенов в моем десериализаторе.

Рабочая версия для моего десериализатора:

public Object deserialize(JsonParser jp, DeserializationContext ctx) throws IOException {
        if(!"type".equals(jp.nextFieldName()) )throw new JsonParseException(jp,"'type' expected");
        String typeVal = jp.nextTextValue();
        if("update".equals(typeVal)) {
            jp.nextValue(); //consume type.
            try {
                JsonDeserializer deser = ctx.findNonContextualValueDeserializer(contentType);
                return new Update<>(deser.deserialize(jp,ctx));
            } catch (Exception ex) {
                throw new IllegalStateException("Could not handle deserialization for type", ex);
            } finally {
                jp.nextToken();
            }
        } else if("keep".equals(typeVal)) {
            jp.nextToken();
            return new Keep<>();
        } else if("reset".equals(typeVal)) {
            jp.nextToken();
            return new Reset<>();
        } else {
            return ctx.handleUnexpectedToken(FieldUpdate.class, jp);
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...