Можно десериализовать в класс с закрытыми полями и собственным конструктором аргумента, не используя аннотации и не модифицируя класс, используя Джексона?
Я знаю, что это возможно в Джексоне при использовании этой комбинации: 1) Java 8, 2) компилировать с опцией "-parameters" и 3) имена параметров соответствуют JSON. Но это также возможно в GSON по умолчанию без всех этих ограничений.
Например:
public class Person {
private final String firstName;
private final String lastName;
private final int age;
public Person(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
public static void main(String[] args) throws IOException {
String json = "{firstName: \"Foo\", lastName: \"Bar\", age: 30}";
System.out.println("GSON: " + deserializeGson(json)); // works fine
System.out.println("Jackson: " + deserializeJackson(json)); // error
}
public static Person deserializeJackson(String json) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES);
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
return mapper.readValue(json, Person.class);
}
public static Person deserializeGson(String json) {
Gson gson = new GsonBuilder().create();
return gson.fromJson(json, Person.class);
}
}
Который отлично работает для GSON, но Джексон бросает:
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of 'jacksonParametersTest.Person' (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (String)"{firstName: "Foo", lastName: "Bar", age: 30}"; line: 1, column: 2]
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
Это возможно в GSON, поэтому я ожидаю, что в Джексоне должен быть какой-то путь без изменения класса Person, без Java 8 и без явного пользовательского десериализатора. Кто-нибудь знает решение?
- Обновление, дополнительная информация
Gson, кажется, пропускает конструктор аргументов, поэтому он должен создавать конструктор без аргументов за кулисами, используя отражения.
Также существует модуль Kotlin Jackson, который может сделать это для классов данных Kotlin, даже без флага компилятора "-parameters". Так что странно, что такого решения, похоже, не существует для Java Jackson.
Это (приятное и чистое) решение, доступное в Kotlin Jackson (которое IMO должно также стать доступным в Java Jackson через пользовательский модуль):
val mapper = ObjectMapper()
.enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES)
.registerModule(KotlinModule())
val person: Person = mapper.readValue(json, Person::class.java)