如何使用 Jackson 将字符串反序列化为自定义对象?

时间:2021-02-11 17:41:58

标签: java json jackson jackson-databind

我有这个 JSON 想要解析:

{
 "name": "john",
}

我必须使用以下层次结构。这些类是不可变的,我必须通过静态工厂方法访问它们(这是必要的,因此建议修改 NamePerson 是没有意义的)。

class Name {
  static Name valueOf(String name) {...}
  private Name() {}
  String name();
}
class Person {
  static Person create(Name name) {...}
  private Person() {...}
  Name name();
}

为此,我想用 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);
  }
}

当然,这行不通。它甚至无法编译。

我知道我可以编写类似于以下内容的内容,但是 Name 到处都在使用,而且并不总是在 Person 中,所以我真的需要一个单独的 {{1} 反序列化器}.

Name

如何在不求助于中间 POJO 的情况下反序列化?

2 个答案:

答案 0 :(得分:1)

如果你可以修改Person,你可以使用@JsonCreator:

@JsonCreator
public static Person create(@JsonProperty("name") String name) {
    Name nameInstance = Name.valueOf(name);
    return new Person(nameInstance);
}

这将正确使用该 JSON,将“name”属性映射到方法的第一个参数。

如果你不能修改类,你可以使用mixin方法,创建mixin:

interface PersonMixin {
    @JsonCreator
    public static Person create(@JsonProperty("name") Name name) {return null;}
}

并在映射器中注册它:

 mapper.addMixIn(Person.class, PersonMixin.class);

答案 1 :(得分:1)

我必须对 parser.getValueAsString() 使用 NameDeserializer,对 codec.treeToValue() 使用 PersonDeserializer

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);
  }
}
相关问题