Как я могу десериализовать вложенную обернутую строку в Джексоне?

У меня есть строка JSON, которая содержит вложенную и обернутую строку JSON. Я хотел бы десериализовать это с помощью Джексона, но я не знаю, как это сделать. Вот пример боба:

@JsonIgnoreProperties(ignoreUnknown = true)
public class SomePerson {

    public final String ssn;
    public final String birthday;
    public final Address address;

    @JsonCreator
    public SomePerson(
            @JsonProperty("ssn") String ssn,
            @JsonProperty("birthday") String birthday,
            @JsonProperty("data") Address address,
            @JsonProperty("related") List<String> related) {
        this.ssn = ssn;
        this.birthday = birthday;
        this.address = address;
    }

    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class Address {

        public final String city;
        public final String country;

        @JsonCreator
        public Address(
                @JsonProperty("city") String city,
                @JsonProperty("country") String country) {
            this.city = city;
            this.country = country;
        }
    }
}

Строка JSON выглядит примерно так:

{
  ssn: "001",
  birthday: "01.01.2020",
  address: "{ city: \"London\", country: \"UK\" }"
}

Хотя я уже десериализовал nsted-объекты раньше, я совершенно не понимаю, как это сделать, когда объект представляет собой обернутую строку.


person Mridang Agarwalla    schedule 13.02.2021    source источник
comment
Почему в вашей модели адрес является строкой? Это должен быть экземпляр типа Address.   -  person Domenico Sibilio    schedule 13.02.2021
comment
Извини, я виноват. Это была опечатка. ????????   -  person Mridang Agarwalla    schedule 13.02.2021
comment
Вы видели мой ответ? Взгляните также на: Можно ли заставить Джексона сериализовать вложенный объект как строку   -  person Michał Ziober    schedule 17.02.2021


Ответы (2)


Когда внутренний объект экранирован JSON String, нам нужно дважды десериализовать его. Первый раз запускается, когда root JSON Object десериализован, а второй раз нам нужно запускать вручную. Для этого нам нужно реализовать собственный десериализатор, реализующий интерфейс com.fasterxml.jackson.databind.deser.ContextualDeserializer. Это может выглядеть так:

class FromStringJsonDeserializer<T> extends StdDeserializer<T> implements ContextualDeserializer {

    /**
     * Required by library to instantiate base instance
     * */
    public FromStringJsonDeserializer() {
        super(Object.class);
    }

    public FromStringJsonDeserializer(JavaType type) {
        super(type);
    }

    @Override
    public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        String value = p.getValueAsString();

        return ((ObjectMapper) p.getCodec()).readValue(value, _valueType);
    }


    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {
        return new FromStringJsonDeserializer<>(property.getType());
    }
}

Нам нужно аннотировать наше свойство этим классом:

@JsonDeserialize(using = FromStringJsonDeserializer.class)
public final Address address;

С этого момента вы сможете десериализовать полезную нагрузку выше JSON в свою модель POJO.

Смотрите также:

person Michał Ziober    schedule 13.02.2021

readValue(String,Class) должен работать:

Address addObject = mapper.readValue(root.getString("address"), Address.class);

Где root – ваш основной JSONObject.

person aran    schedule 13.02.2021