Джексон добавляет несуществующее поле во время сериализации - PullRequest
0 голосов
/ 26 марта 2020

Mapper:

public static ObjectMapper mapper = new ObjectMapper()
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            .setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
            .enable(SerializationFeature.INDENT_OUTPUT);

Класс для сериализации:

@Builder(builderClassName = "GooglePlayGameBuilder", toBuilder = true)
@JsonDeserialize(builder = GooglePlayGame.GooglePlayGameBuilder.class)
public final class GooglePlayGame  {

    @JsonProperty("Title") private final String title;
    @JsonProperty("Genre") private final String genre;
    @JsonProperty("Price") private final String price;
    @JsonProperty("Last updated") private final String lastUpdated;
    @JsonProperty("Current version") private final String currentVersion;
    @JsonProperty("Requirements") private final String requiresAndroid;
    @JsonProperty("IAP") private final String IAP;
    @JsonProperty("Contacts") private final String devEmail;

...

Добавить объект на карту, а затем я хочу сериализовать мою карту:

public static volatile ConcurrentMap<String, GooglePlayGame> games = new ConcurrentSkipListMap<>(String.CASE_INSENSITIVE_ORDER);

Write в файл:

public static void saveLibraryToFile(){
        try {
            mapper.writeValue(new File(LIBRARY_FILENAME), games);
        } catch (IOException e) {
            log.error("[Couldn't write to file] ", e.getMessage());
        }
    }

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

{
  "Never Alone: Ki Edition" : {
    "Title" : "Never Alone: Ki Edition",
    "Genre" : "Adventures",
    "Price" : "4,99 €",
    "Last updated" : "September 15, 2016",
    "Current version" : "1.0.0",
    "Requirements" : "2.3+",
    "IAP" : "nope",
    "Contacts" : "support@neveralonegame.com"
  },
...

Если я буду комментировать свой класс с помощью lombok @Getter, появится странное поле:

{
  "Never Alone: Ki Edition" : {
    "iap" : "nope"
    "Title" : "Never Alone: Ki Edition",
    "Genre" : "Adventures",
    "Price" : "4,99 €",
    "Last updated" : "September 15, 2016",
    "Current version" : "1.0.0",
    "Requirements" : "2.3+",
    "IAP" : "nope",
    "Contacts" : "support@neveralonegame.com"
  },

Я не понимаю это поле:

"iap" : "nope"

Откуда Джексон его нашел? Я проверил свою локальную карту с журналами и все в порядке, это поле не существует, но во время сериализации оно появляется.

Ответы [ 3 ]

1 голос
/ 26 марта 2020

Я не знаю, есть ли у вас какие-либо ограничения ... Но я рекомендую вам использовать camelCase для имени вашей переменной. Я считаю, что ваша проблема вызвана геттером, сгенерированным Lombok.

1 голос
/ 27 марта 2020

Ломбок создаст метод получения для поля IAP с именем getIap(). Затем Джексон автоматически определит это как свойство с именем iap. Поскольку имена свойств чувствительны к регистру, это свойство отличается от свойства IAP, определенного аннотацией @JsonProperty("IAP").

У вас есть 2 варианта:

  • Переименуйте поле в iap, оставьте аннотацию без изменений.
    Рекомендуется, поскольку это соответствует стандарту Java.

  • Добавьте следующую аннотацию к классу:

    @JsonAutoDetect(getterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE)
    

    Это останавливает Джексона от автоматического определения свойств от методов получения, то есть только методы получения, помеченные @JsonProperty, будут определять свойство. Поскольку ни один из созданных в Lombok геттеров не будет иметь такой аннотации, эффект будет состоять в том, что только аннотированные поля будут определять свойства.

1 голос
/ 26 марта 2020

Я согласен с пользователем 2447161. Lombok пытается создать правильное имя получателя для «IAP», но Джексон и Ломбок не согласны с тем, как нестандартные имена переменных должны становиться получателями, поэтому Джексон не знает, что два IAP (переменная и получатель) одинаковы. Переименуйте вашу переменную в «iap», и все будет хорошо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...