#java #json #jackson #lombok
#java #json #Джексон #ломбок
Вопрос:
У меня возникла странная проблема, поскольку я переношу код с Java 8 и Sprint Boot 1.X на 11 и 2.X. Ранее я обнаружил, что Джексон сериализует private boolean isAvailable
оба available: false
и isAvailable: false
. Чтобы добавить больше путаницы, Lombok готов к работе, поэтому у меня нет видимости на получателе, и если это вызывает конфликт. Ниже приведен код класса Java:
@Data
public class Availability{
@JsonProperty("isAvailable")
private boolean isAvailable;
}
И повторный запуск JSON из Jackson Object mapper был:
"Availability" : [{
"isAvailable" : false,
"available" : false }]
Это было с Jackson 2.8. Теперь с Jackson 2.10 я получаю isAvailable: false
только в качестве выходных данных в JSON из ObjectMapper.
"Availability" : [{
"isAvailable" : false }]
Для меня имеет смысл, что оно должно соответствовать только имени переменной Java, но контракт, к сожалению, имеет обе версии, и я не хочу менять контракт. Некоторые используют is, а некоторые нет. Я знаю, что возможен пользовательский сериализатор, но не уверен, как это сделать и нужно ли это.
Ответ №1:
Это lombok поле, взаимодействующее.
Давайте возьмем этот гипотетический класс (здесь вообще не задействован ломбок или, если уж на то пошло, Джексон):
class Example {
public boolean isAvailable() {
return true;
}
}
Согласно спецификации beanspec, Example
класс имеет единственное доступное только для чтения свойство bean типа boolean, вызываемое available
. Это потому, что любой метод без аргументов, который возвращает логическое значение и начинается с is
(а затем с заглавной буквы), считается средством доступа, и чтобы добраться до его имени, is
удалите.
Так что посмотрим на это с этой стороны. Теперь давайте посмотрим на это с другой стороны, вы пишете класс, в котором по какой-либо причине вы решили, что полю должно быть присвоено имя isAvailable
. Реальный вопрос заключается в следующем: как вы хотите, чтобы «свойство» было названо (в соответствии со спецификацией beanspec)? Если это действительно должно быть вызвано isAvailable
, есть только один способ добиться этого:
class Example {
public boolean isIsAvailable() {
return true;
}
}
Да, isIsAvailable
. Выглядит глупо, но это то, что предписывают правила, если вы хотите, чтобы вызывалось само свойство isAvailable
. Ломбок решил (ИСТОЧНИК: я основной участник), что никому на самом деле не нужен метод с именем, isIsAvailable
когда вы вставляете @Getter
аннотацию в поле с именем isAvailable
.
Итак, теперь у вас есть класс, который эффективно выглядит, насколько это касается Джексона:
class Availability {
@JsonProperty("isAvailable") private boolean isAvailable;
public boolean isAvailable() { return this.isAvailable; }
}
Не используя никаких специальных интеллектуальных данных, просто применяя правила literal, означает, что Джексон говорит: Хорошо, здесь есть 2 разных свойства, available
(получаемые путем вызова isAvailable()
) и isAvailable
поле. Для геттеров в стиле beanspec is
/ get
удаляется, для полей это не так, особенно если вы вставляете там @JsonProperty("isAvailable")
.
Это контекст, объясняющий, почему все это происходит.
Решением могло бы быть создание этого метода:
@JsonProperty("available")
public boolean getAvailable() { return this.available; }
Я думаю, что это даст вам оба варианта в вашем выводе JSON.
Комментарии:
1. Я ценю ваши комментарии. Работа с устаревшим кодом — это, конечно, неприятность, и я понимаю спецификацию Java bean и то, как Джексону и Ломбоку приходится иметь с этим дело. Я немного озадачен тем, почему поведение изменилось при изменении зависимостей, а базовый pojo не был изменен.
2. Я бы сказал, что обычно вывод ‘available’ и ‘isAvailable’ таким образом нежелателен, поэтому, предположительно, jackson обновлен до того же уровня интеллекта, что и lombok. Мы в lombok несколько раз нарушали обратную совместимость в таких экзотических случаях, не придавая этому особого значения (без версии 2.0 или чего-то еще), может быть, они тоже?
3. Я скажу вам, что написание getter со свойством json таким образом, безусловно, сработало, но пришло время договориться с клиентами и изменить контракт. Почему никто не заметил этого раньше, отстой. Я ненавижу наследование кода, но иногда такова жизнь в мире программного обеспечения! Еще раз спасибо, и Lombok, кстати, является шаблонным спасением.