使用Jackson,我想将一些值反序列化为泛型 Package 器对象,对于这些对象,我为每种类型都有一个特定的静态工厂方法。
然而,Jackson似乎并没有注意到这一层的间接性,即使我使用@JsonCreator
注解工厂方法。
定义无效异常:无法构造Wrapped
的示例(不存在创建者,如默认构造函数):没有字符串参数构造函数/工厂方法可从字符串值(“Carl”)反序列化
如何让Jackson使用返回泛型类型 Package 器的工厂方法?
这个自包含的代码说明了我的问题:
class Request {
// I want to deserialize into these fields
@JsonProperty Wrapped<Person> person;
@JsonProperty Wrapped<Score> score;
}
class Wrapped<T> {
// This is my generic wrapper type.
// Its construction is non-trivial: it is impossible to first construct the value before wrapping it.
// Therefor, construction is performed by the factory methods of the concrete value classes (Person, Score, ...).
// Let's say for simplicity that it did have a simple constructor:
T value;
public Wrapped(T value) {
this.value = value;
}
}
class Person {
@JsonCreator
public static Wrapped<Person> createWrapped(String name) {
// complex construction of the wrapped person
return new Wrapped<>(new Person(name));
}
@JsonValue
String name;
public Person(String name) {
this.name = name;
}
}
class Score {
@JsonCreator
public static Wrapped<Score> createWrapped(int score) {
// complex construction of the wrapped score
return new Wrapped<>(new Score(score));
}
@JsonValue
int score;
public Score(int score) {
this.score = score;
}
}
class Example {
private static final String JSON_REQUEST =
"""
{
"person":"Carl",
"score":20
}
""";
public static void main(String[] args) throws Exception {
Request request = new ObjectMapper()
.readValue(JSON_REQUEST, Request.class);
System.out.println(request.person.value.name);
System.out.println(request.score.value.score);
}
}
值得注意的是,类型信息只存在于Java类中,而不应该存在于JSON中。
2条答案
按热度按时间6kkfgxo01#
一种解决方案是添加DTO:
并将请求定义更改为使用模式。
20jt8wwn2#
@p3consulting的回答让我找到了正确的方向,但却导致了完全不同的结果。
Jackson有一个叫Converter的东西,它完全符合我的要求。
我为每个 Package 的值类型创建了转换器,
然后注解请求中的属性以使用这些转换器:
对于具有更复杂签名的工厂方法,可以通过使用DTO来实现,例如:
我不敢相信这是如此简单,但我花了这么长时间才找到。