Оборачивание полей Json в переменную экземпляра pojo - PullRequest
0 голосов
/ 25 января 2019

Я пытаюсь сопоставить определенные поля JSON с переменной экземпляра класса.

Мой образец Персона класс выглядит так:

public class Person {
   private String name;
   private Address address;

   //many more fields 

   //getters and setters
}

Образец Адрес Класс:

public class Address {
   private String street;
   private String city;
   //many more fields 

   // getters and setters
}

Объект json, подлежащий десериализации в мой класс Person, не содержит поля «address».Это выглядит так:

{
"name":"Alexander",
"street":"abc 12",
"city":"London"
}

Есть ли способ десериализации json в pojo Person, где поля Address также отображаются правильно?

Я использовал собственный десериализатор адресов, как упоминалось во многих постах здесь.Однако он не вызывается, так как объект Json не содержит поля «адрес».

Я решил эту проблему, сопоставив каждое поле вручную с помощью JsonNode, однако в моем реальном проекте это не очень хорошее решение.

Есть ли способ обойти такую ​​проблему с помощью Джексона?Плюс, если этот вопрос был задан ранее, то извиняюсь от моего имени, так как я интенсивно искал решение и, возможно, еще не видел его..

Ответы [ 3 ]

0 голосов
/ 25 января 2019

Я понял вашу проблему так, что речь идет о плоском Json, который имеет все поля Address на том же уровне, что и Person.Даже если это не совсем так, это может вам помочь.JsonDeserializer будет хорошо, но вам нужно применить его к Person, потому что это уровень, на котором находятся все поля.

Вот так:

public class CustomDeserializer extends JsonDeserializer<Person> {

    // need to use separate ObjectMapper to prevent recursion
    // this om will not be registered with this custom deserializer
    private final ObjectMapper om;
    {
        om = new ObjectMapper();
        // this is needed because flat json contains unknown fields
        // for both types.
        om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    @Override
    public Person deserialize(JsonParser parser, DeserializationContext ctxt)
        throws IOException, JsonProcessingException {
        // make a string of json tree so not any particular object
        String json = om.readTree(parser).toString();
        // deserialize it as person (ignoring unknown fields)
        Person person = om.readValue(json, Person.class);
        // set address deserializing it from teh same string, same manner
        person.setAddress(om.readValue(json, Address.class));
        return person;
    }

}

Конечно, этоэто не единственный способ и может не иметь наилучшей производительности, но он касается только того, как вы выполняете десериализацию в своем настраиваемом десериализаторе.Если ваши Person & Address объекты имеют как 10 полей, каждое из которых использует это, не должно быть проблемой.

Обновление

Я думаю, что в вашем случае -основываясь на данных вашего примера - ответ Михаэля Зибера может быть лучшим, но если вам нужна более сложная обработка, чем обычное развертывание для ваших данных, вам просто нужно десериализовать класс Person так, как я представил.

0 голосов
/ 26 января 2019

@JsonUnwrapped аннотация была введена для этой проблемы. Модель:

class Person {
    private String name;

    @JsonUnwrapped
    private Address address;

    // getters, setters, toString
}
class Address {
    private String street;
    private String city;

    // getters, setters, toString
}

Использование:

ObjectMapper mapper = new ObjectMapper();
String json = "{\"name\":\"Alexander\",\"street\":\"abc 12\",\"city\":\"London\"}";
System.out.println(mapper.readValue(json, Person.class));

Печать:

Person{name='Alexander', address=Address{street='abc 12', city='London'}}

Для получения дополнительной информации читайте:

  1. Примеры аннотаций Джексона
  2. Тип аннотации JsonUnwrapped
  3. Джексон JSON - Использование @JsonUnwrapped для сериализации / десериализации свойств в качестве выравнивающей структуры данных
0 голосов
/ 25 января 2019

Я не думаю, что у вас действительно есть проблема десериализации, а скорее общая проблема Java: как убедиться, что поле address всегда содержит значение. Все, что вам нужно сделать, это либо присвоить address значению по умолчанию в конструкторе Person, либо создать и назначить значение по умолчанию для address в методе Person.getAddress.

...