杰克逊的动态根元素

robin850:

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

基本上我有这个:

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

输出如下:

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

但是可以预期的是:

<someType></someType>

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

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

MichałZiober:

我假设NodeDocument包含的不只是一个属性。在这种情况下,您需要实现自定义序列化程序,BeanSerializerModifier并允许您序列化所有属性。下面的代码显示了完整的解决方案:

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>

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章