Предыстория: я обнаружил «недействительный» код в проекте Spring-Admin: «Невозможно создать экземпляр регистрации (не существует создателей, таких как конструкция по умолчанию)».Поэтому я написал собственный десериализатор и доложил о проблеме.Но отчет был отклонен, так как он якобы работает.И после повторного тестирования это похоже на работу сейчас.Не имеет смысла.Поэтому я хотел бы знать, , почему этот код работает.
Но здесь есть одна загвоздка.Когда я написал аналогичный тестовый класс, он не работает в моем проекте.Даже когда я буквально беру код «ныне работающего» класса регистрации и пробую его в собственном проекте, это просто не десериализуется.И затем, с практически идентичным классом, это работает.Это не имеет никакого смысла.
https://github.com/codecentric/spring-boot-admin/blob/master/spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/server/domain/values/Registration.java
Следующий пост объясняет, как работает комбо lombok-jackson, но здесь он не работает.Я совершенно сбит с толку, это невероятно нелепая ситуация, когда (ненужное) упрощение создает превосходную сложность.Но я хотел бы понять это, так как я могу снова учесть эту ситуацию в будущем.
Сбой десериализации Джексона из-за не стандартного конструктора, созданного lombok
Такчтобы иметь что-то простое в работе: здесь у нас есть хороший и работающий чистый Джексон:
public class TestTO_pureJackson {
private final String a;
private final String b;
@JsonCreator
private TestTO_pureJackson(@JsonProperty("a") String a, @JsonProperty("b") String b) {
this.a = a;
this.b = b;
}
}
и здесь у нас нет рабочего эквивалента в ломбках (даже если я удаляю одно поле, так что это «то же самое» для последнего примера):
@lombok.Data
public class TestTO {
private final String a;
private final String b;
@lombok.Builder(builderClassName = "Builder")
private TestTO(String a, String b) {
this.a = a;
this.b = b;
}
public static TestTO.Builder create(String a) {
return builder().a(a);
}
}
и мы пытаемся десериализовать:
{"a": "a", "b": "b"}
Может кто-нибудь понять магию под капотом и помочь мне понять, что здесь не так?
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<scope>provided</scope>
</dependency>
И чтобы сделать это еще более нелепым (вы действительно видите какую-либо существенную разницу с TestTO ???), работает следующий код:
@lombok.Data
public class Pair {
private final String left;
private final String right;
@lombok.Builder(builderClassName = "Builder")
private Pair(String pairId) {
left = pairId.substring(0, 3).toUpperCase(Locale.US);
right = pairId.substring(3).toUpperCase(Locale.US);
}
}
и метод main:
public class PairTest {
public static final String DATA = "[\"btcusd\",\"ltcusd\",\"ltcbtc\"]";
public static void main(String[] args) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
Pair[] pairs = objectMapper.readValue(DATA, Pair[].class);
for (Pair pair : pairs) {
System.out.println(pair);
}
}
}
Кто-нибудь может понять, почему два почти одинаковых класса TO ведут себя по-разному?