[英]How do I deserialize a string as a custom object with Jackson?
I have this JSON that I want to parse:我有这个要解析的 JSON:
{
"name": "john",
}
I must use the following hierarchy.我必须使用以下层次结构。 The classes are immutable and I must access them by the static factory method (this is imperative, so it makes no sense to suggest modifications to either
Name
or Person
).这些类是不可变的,我必须通过 static 工厂方法访问它们(这是必要的,因此建议对
Name
或Person
进行修改是没有意义的)。
class Name {
static Name valueOf(String name) {...}
private Name() {}
String name();
}
class Person {
static Person create(Name name) {...}
private Person() {...}
Name name();
}
To that end, I want to deserialize a Person
with Jackson, so I wrote this:为此,我想用 Jackson 反序列化一个
Person
,所以我写了这个:
public class NameJsonDeserializer extends JsonDeserializer<Name> {
@Override public Name deserialize(JsonParser parser, DeserializationContext context) {
var tree = parser.getCodec().readTree(parser);
var name = tree.asToken().asString();
return Name.valueOf(name);
}
}
public class PersonJsonDeserializer extends JsonDeserializer<Person> {
@Override public Person deserialize(JsonParser parser, DeserializationContext context) {
var tree = parser.getCodec().readTree(parser);
var name = (ObjectNode) tree.get("name");
return Person.create(name);
}
}
But of course, this doesn't work.但是,当然,这是行不通的。 It doesn't even compile.
它甚至不编译。
I know I can write something similar to the following, but Name
is used all over the place, and not always within a Person
, so I really need a separate deserializer for Name
.我知道我可以编写类似于以下内容的内容,但是
Name
到处都在使用,而且并不总是在Person
中,所以我真的需要一个单独的Name
反序列化器。
var tree = parser.getCodec().readTree(parser);
var name = (TextNode) tree.get("name");
return Person.create(Name.valueOf(name.asText()));
How can I deserialize without having recourse to intermediary POJOs?如何在不求助于中间 POJO 的情况下进行反序列化?
I must use parser.getValueAsString()
for NameDeserializer
and codec.treeToValue()
for PersonDeserializer
:我必须对 NameDeserializer 使用
parser.getValueAsString()
,对NameDeserializer
使用PersonDeserializer
( codec.treeToValue()
:
public class NameJsonDeserializer extends JsonDeserializer<Name> {
@Override public Name deserialize(JsonParser parser, DeserializationContext context) {
var name = parser.getValueAsString();
return Name.valueOf(name);
}
}
public class PersonJsonDeserializer extends JsonDeserializer<Person> {
@Override public Person deserialize(JsonParser parser, DeserializationContext context) {
var codec = parser.getCodec();
var tree = codec.readTree(parser);
var name = codec.treeToValue(tree.get("name"), Name.class);
return Person.create(name);
}
}
If you can modify Person, you could use @JsonCreator:如果你可以修改 Person,你可以使用 @JsonCreator:
@JsonCreator
public static Person create(@JsonProperty("name") String name) {
Name nameInstance = Name.valueOf(name);
return new Person(nameInstance);
}
This will consume that JSON properly, mapping the "name" property to the first param of the method.这将正确消耗 JSON,将“名称”属性映射到方法的第一个参数。
If you cannot modify the class you can use the mixin approach, creating the mixin:如果您无法修改 class 您可以使用 mixin 方法,创建 mixin:
interface PersonMixin {
@JsonCreator
public static Person create(@JsonProperty("name") Name name) {return null;}
}
and register it in the mapper:并在映射器中注册:
mapper.addMixIn(Person.class, PersonMixin.class);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.