Jackson xml 模块:使用 @JacksonXmlText 属性反序列化不可变类型

2022-09-03 07:35:19

我想将不可变类型序列化为json和xml:

序列化的 JSON 如下所示:

{
    "text" : "... the text..."
}

序列化的 xml 是这样的:

 <asText>_text_</asText>

(请注意,文本是 xml 的元素文本)

Java 对象是这样的:

@JsonRootName("asText")
@Accessors(prefix="_")
public static class AsText {

    @JsonProperty("text") @JacksonXmlText
    @Getter private final String _text;

    public AsText(@JsonProperty("text") final String text) {
        _text = text;
    }
}

请注意,_text 属性是最终属性(因此对象是不可变的),并且带有注释,以便序列化为 xml 元素的文本@JacksonXmlText

由于对象是不可变的,因此需要来自文本的构造函数,并且构造函数的参数必须用@JsonProperty

    public AsText(@JsonProperty("text") final String text) {
        _text = text;
    }

当序列化/反序列化到/从JSON反序列化时,一切正常...当序列化/反序列化到/从 XML 反序列化时出现问题:

 // create the object
 AsText obj = new AsText("_text_");

 // init the mapper
 XmlMapper mapper = new XmlMapper();

 // write as xml
 String xml = mapper.writeValueAsString(obj);
 log.warn("Serialized Xml\n{}",xml);

 // Read from xml
 log.warn("Read from Xml:");
 AsText objReadedFromXml = mapper.readValue(xml,
                                              AsText.class);
 log.warn("Obj readed from serialized xml: {}",
          objReadedFromXml.getClass().getName());

例外情况是:

    com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "" (class r01f.types.url.UrlQueryStringParam), not marked as ignorable (2 known properties: "value", "name"])

xml 模块似乎需要对对象的构造函数进行注释,如下所示:

    public AsText(@JsonProperty("") final String text) {
        _text = text;
    }

但这甚至不起作用:

    com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `test.types.SerializeAsXmlElementTextTest$AsText` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

需要构造函数参数处的注释才能从 JSON 反序列化@JsonProperty("text")

...我怎么能让它工作


答案 1

尝试为属性添加公共 getter。我认为这应该可以解决反序列化问题。

@JsonRootName("asText")
@Accessors(prefix = "_")
public static class AsText {

    @JsonProperty("text")
    @JacksonXmlText
    @Getter
    private final String _text;

    public AsText(@JsonProperty("text") final String text) {
        _text = text;
    }

    public String getText() {
        return _text;
    }
}

实际上,它的工作原理也无需添加一个getter,这些版本的Lombak&Jackson。

<dependencies>
    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
        <version>2.9.0</version>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.18</version>
    </dependency>
</dependencies>

答案 2

我遇到了同样的错误“没有基于委托或属性的创建者”的问题。在我的情况下,这是不可变版本2.5.6的问题。我已将其降级到版本2.5.5来修复它。版本2.5.6在 mvnrepository.com 但官方页面上被标记为2.5.5的稳定版本。


推荐