简体   繁体   English

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

[英]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 工厂方法访问它们(这是必要的,因此建议对NamePerson进行修改是没有意义的)。

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.

相关问题 如何编写自定义的Jackson解串器,将包含原始json的json对象反序列化为单个对象? - How do I write a custom Jackson deserializer to deserialize a json object that contains raw json into a single object? 如何使用Jackson反序列化对象变量? - How do I deserialize object variables using Jackson? 如何反序列化地图<String,Object>正确地在杰克逊 - How to Deserialize a Map<String,Object> correctly in Jackson 如何使用Jackson来反序列化此JSON? - How do I deserialize this JSON using Jackson? 如何使用 Jackson 反序列化以秒为单位的时间戳? - How do I deserialize timestamps that are in seconds with Jackson? 杰克逊:反序列化地图 <String,Object> 自定义嵌套Pojo - Jackson: Deserialize map<String,Object> to Custom nested Pojo 使用Jackson反序列化为String或Object - Deserialize to String or Object using Jackson 如何将 JSON 反序列化为地图<String, Object>成员变量使用杰克逊? - How can I deserialize JSON to a Map<String, Object> member variable using Jackson? How do I deserialize to Boolean.class from Json object in case insensitive manner using Jackson? - How do I deserialize to Boolean.class from Json object in case insensitive manner using Jackson? 如何使用Jackson和RestTemplate将24小时日期字符串反序列化为LocalDate - How do I deserialize 24 hour date string to LocalDate using Jackson and RestTemplate
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM