杰克逊的动态根元素 [英] Dynamic root element with Jackson

查看:77
本文介绍了杰克逊的动态根元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在处理一个项目,该项目处理的元素(由于遗留原因)必须具有表示其类型的标签名称.

I'm currently working on a project that deals with elements that (for legacy reasons) must have a tag name that represents their type.

基本上我有这个:

@JsonRootName("node")
class NodeDocument {
    private String type;
}

输出类似:

<node type="someType"></node>

但是可以预期的是:

<someType></someType>

@JsonRootName似乎无法在方法或属性上使用.

@JsonRootName doesn't seem to be usable on a method or attribute.

即使有SerializationConfig.withRooName()或自定义序列化程序,我似乎也找不到一种用存储在对象本身中的动态值定义根名称的方法.

Even though there is SerializationConfig.withRooName() or custom serializers, I can't seem to find a way to define the root name with a dynamic value stored in the object itself.

推荐答案

我假定NodeDocument包含多个属性.在这种情况下,您需要将自定义序列化程序与BeanSerializerModifier一起实现,以允许您序列化所有属性.下面的代码显示了完整的解决方案:

I assume NodeDocument contains more than just one property. In that case you need to implement custom serialiser together with BeanSerializerModifier which allow you to serialise all properties. Below code shows complete solution:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.fasterxml.jackson.databind.util.NameTransformer;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;

import javax.xml.namespace.QName;
import java.io.IOException;
import java.util.Objects;

public class XmlJacksonApp {

    public static void main(String... args) throws Exception {
        SimpleModule dynamicRootNameModule = new SimpleModule();
        dynamicRootNameModule.setSerializerModifier(new DynamicRootNameBeanSerializerModifier());

        XmlMapper mapper = XmlMapper.xmlBuilder()
                .enable(SerializationFeature.INDENT_OUTPUT)
                .addModule(dynamicRootNameModule)
                .build();
        NodeDocument element = new NodeDocument();
        element.setId(123);
        element.setName("Rick and Morty.doc");
        element.setType("sitcom");

        mapper.writeValue(System.out, element);
    }
}

class DynamicRootNameBeanSerializerModifier extends BeanSerializerModifier {
    @Override
    public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
        if (beanDesc.getBeanClass() == NodeDocument.class) {
            return new NodeDocumentJsonSerializer((JsonSerializer<NodeDocument>) serializer);
        }
        return super.modifySerializer(config, beanDesc, serializer);
    }
}

class NodeDocumentJsonSerializer extends JsonSerializer<NodeDocument> {
    private final JsonSerializer<NodeDocument> serializer;

    NodeDocumentJsonSerializer(JsonSerializer<NodeDocument> serializer) {
        this.serializer = Objects.requireNonNull(serializer);
    }

    @Override
    public void serialize(NodeDocument value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        ToXmlGenerator xmlGen = (ToXmlGenerator) gen;
        writeDynamicRootName(value.getType(), xmlGen);
        serializeProperties(value, gen, serializers);
        writeEndObject(xmlGen);
    }

    private void writeDynamicRootName(String rootName, ToXmlGenerator xmlGen) throws IOException {
        xmlGen.setNextName(new QName("", rootName));
        xmlGen.writeStartObject();
    }

    private void serializeProperties(NodeDocument value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        serializer.unwrappingSerializer(NameTransformer.NOP).serialize(value, gen, serializers);
    }

    private void writeEndObject(ToXmlGenerator xmlGen) throws IOException {
        xmlGen.writeEndObject();
    }
}

class NodeDocument {

    @JsonIgnore
    private String type;
    private int id;
    private String name;

    // getters, setters
}

上面的代码显示:

<sitcom>
  <id>123</id>
  <name>Rick and Morty.doc</name>
</sitcom>

这篇关于杰克逊的动态根元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆