Постконструкция Джексона Маппера - PullRequest
29 голосов
/ 26 июля 2011

Я использую Jackson ObjectMapper для десериализации некоторого JSON в класс Java, который мы назовем PlayerData. Я хотел бы добавить немного логики в класс PlayerData, чтобы исправить некоторые данные после загрузки полей. Например, некоторые ранние файлы JSON раньше использовали флаг "sex" вместо "гендерного" falg , поэтому, если установлен флаг пола, но флаг пола не установлен, я бы хотел установить значение поля пола равным значению поля пола.

Есть ли какая-нибудь аннотация @PostConstruct или @AfterLoad, которую я мог бы прикрепить к методу? Или, может быть, интерфейс, который я мог бы реализовать? Я не заметил ни одного в документации, но это казалось очевидной особенностью.

Ответы [ 3 ]

16 голосов
/ 28 ноября 2016

Найден через ссылку в комментариях (кредит: fedor.belov ) Похоже, это позволяет вам запускать пост-конструкцию кода.

Добавление комментария для людей, которые попали сюда через http://jira.codehaus.org/browse/JACKSON-645 или http://jira.codehaus.org/browse/JACKSON-538 и ищем метод, который вызывается после завершения десериализации. я мог достичь желаемого эффекта, добавив аннотацию и написав преобразователь, который использует тот же класс, что и вход и выход.

@JsonDeserialize(converter=MyClassSanitizer.class)  // invoked after class is fully deserialized
public class MyClass {
    public String field1;
}

import com.fasterxml.jackson.databind.util.StdConverter;
public class MyClassSanitizer extends StdConverter<MyClass,MyClass> {
  @Override
  public MyClass convert(MyClass var1) {
    var1.field1 = munge(var1.field1);
    return var1;
  }
}
6 голосов
/ 26 июля 2011

Если вы не используете @JsonCreator, то Джексон будет использовать методы установки и получения для установки полей.

Так что если вы определяете следующие методы, предполагая, что у вас есть Sex и Gender перечисления:

@JsonProperty("sex")
public void setSex(final Sex sex) {
  this.sex = sex;
  if (gender == null) {
    gender = (sex == Sex.WOMAN) ? Gender.WOMAN : Gender.MAN;
  }
}

@JsonProperty("gender")
public void setGender(final Gender gender) {
  this.gender = gender;
  if (sex == null) {
    sex = (gender == Gender.WOMAN) ? Sex.WOMAN : Sex.MAN;
  }
}

это будет работать.

Обновление : Вы можете найти все аннотации библиотеки Джексона здесь .

Обновление2 : Другое решение:

class Example {
  private final Sex sex;
  private final Gender gender;

  @JsonCreator
  public Example(@JsonProperty("sex") final Sex sex) {
    super();
    this.sex = sex;
    this.gender = getGenderBySex(sex)
  }

  @JsonFactory
  public static Example createExample(@JsonProperty("gender") final Gender gender) {
    return new Example(getSexByGender(gender));
  }

  private static Sex getSexByGender(final Gender) {
    return (gender == Gender.WOMAN) ? Sex.WOMAN : Sex.MAN;
  }

  private static Gender getGenderBySex(final Sex) {
    return (sex == Sex.WOMAN) ? Gender.WOMAN : Gender.MAN;
  }

}
4 голосов
/ 27 июля 2011

Это то, что на самом деле было предложено пару раз ранее.Так что, может быть, регистрация RFE будет иметь смысл;Есть несколько способов, которыми это может сработать: очевидные из них - это возможность аннотировать тип (@JsonPostProcess (Processor.class)) и возможность регистрировать постпроцессор через Module API (так что в основном существует обратный вызов, когда Джексон создает десериализатор,модуль указывает постпроцессор для использования, если таковые имеются).Но, возможно, есть еще лучшие способы сделать это.

...