Могу ли я использовать сопоставленные свойства Jackson Mixin для создания подкласса JSON при десериализации?

У меня вывод JSON правильно аннотирован и сопоставлен с миксинами для класса User с соответствующими установщиками и получателями для этих свойств:

 public class User {
      String first;
      String middle;
      String last;

      ...
 }

Когда я использую свой миксин:

 public interface UserMixin {
     @JsonProperty("first")
     void setFirst(String first);

     @JsonProperty("middle")
     void setMiddle(String middle);

     @JsonProperty("last")
     void setLast(String last);
 }

После регистрации миксина и записи класса User с помощью ObjectMapper я получаю:

 "User" :
 {
     "first"  : "William",
     "middle" : "S",
     "last"   : "Preston"
 }

Итак, до сих пор, для краткости, я немного соврал - User, как указано выше, представляет собой большой устаревший класс DTO, устойчивый к изменениям.

И хотя миксин отлично работает, наш клиент предпочел бы увидеть что-то вроде:

 "User" :
 {
     "Name" : 
     {
         "first"  : "William",
         "middle" : "S",
         "last"   : "Preston"
     }

     ...
 }

Повторяю, DTO устойчив к изменениям. В идеале я бы реорганизовал DTO и сделал это правильно.

Думаю, я спрашиваю - есть ли какая-то комбинация Mixin / Annotation, которую я могу использовать для подкласса «Name» из уже существующих данных в классе User? Подкласса Name нет ... но все части, необходимые для «записи» JSON в этом формате, существуют.


person hrrf    schedule 10.06.2014    source источник
comment
Я думаю, лучшее, что вы можете сделать, - это создать свой собственный JsonSerializer.   -  person Sotirios Delimanolis    schedule 11.06.2014
comment
Обратный путь тривиален - @JsonUnwrapped. К сожалению, насколько мне известно, автоматическая упаковка значения не поддерживается.   -  person Mark Peters    schedule 11.06.2014


Ответы (1)


Из-за отсутствия аннотации @JsonWrapped моим личным предпочтительным решением здесь было бы использовать converter функциональность @JsonSerialize (похоже, для этого вам понадобится Jackson 2.3+; аннотация поддерживается в 2.2.2, но я получил неожиданные ошибки времени выполнения) .

По сути, converter позволяет выполнять преобразование перед сериализацией из одной структуры данных в другую. Это позволяет вам работать с простыми классами данных, а не тратить время на создание собственного сериализатора.

Во-первых, смоделируйте свой DTO так, как вы хотите, чтобы он был сериализован:

public static class UserDto {
    private final Name name;

    private UserDto(Name name) { this.name = name; }

    public static UserDto fromUser(User user) {
        return new UserDto(Name.fromUser(user));
    }

    public Name getName() { return name; }

    public static class Name {
        private final String first;
        private final String middle;
        private final String last;

        private Name(String first, String middle, String last) {
            this.first = first;
            this.middle = middle;
            this.last = last;
        }

        public static Name fromUser(User user) {
            return new Name(user.getFirst(), user.getMiddle(), user.getLast());
        }

        public String getFirst() { return first; }
        public String getMiddle() { return middle; }
        public String getLast() { return last; }
    }
}

Затем создайте простой класс Converter (я вложил его в UserDto):

    public static class Converter extends StdConverter<User, UserDto> {
        @Override
        public UserDto convert(User value) {
            return UserDto.fromUser(value);

        }
    }

Затем используйте этот класс конвертера в своем миксине:

@JsonSerialize(converter = UserDto.Converter.class)
public interface UserMixin {
}
person Mark Peters    schedule 10.06.2014
comment
Это работает: создание промежуточного POJO между устаревшим пользовательским DTO позволяет нам преобразовать в нужный формат, а также упростить некоторые устаревшие беспорядки, которые нам не нужны. Спасибо! - person hrrf; 11.06.2014