首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Jackson: XML-Binding - Handling Null与空字符串

Jackson: XML-Binding - Handling Null与空字符串
EN

Stack Overflow用户
提问于 2014-01-09 01:50:43
回答 2查看 5.7K关注 0票数 3

新的Jackson-API为我们提供了方便的XML绑定(例如,就像JAXB ),但是我找不到任何方法来使Jackson序列化典型的"xsi:nil"-Attribute,它是用XML表示空值的事实标准?如果我看错了,请纠正我;-)

在JAXB中,这可以通过使用@XMLElement(nillable=true)注释java变量来轻松完成

另请参阅:http://blog.bdoughan.com/2012/04/binding-to-json-xml-handling-null.html

杰克逊能做到吗?

关于Jackson-XML,请参阅:https://github.com/FasterXML/jackson-dataformat-xml

EN

回答 2

Stack Overflow用户

发布于 2014-02-10 01:30:49

这并没有回答这个问题,但是提供了一个变通方法(非常麻烦)!

我设法为jackson编写了一些自定义的序列化程序/反序列化程序(直到jackson官方支持xsi:nil),它们允许以下内容:

如果在POJO

  • deserialize硬编码类型(String,Integer,Float...)的列表中,
  • 将POJO中的值序列化为xsi:nil元素,则将这些值序列化为XML-String。如果在给定的XML-String

中将它们定义为xsi:nil元素,则它们对于POJO为NULL

使用此代码,可以提供与其他xml绑定库(JAXB..)的互操作性。这只能与空值的xsi:nil一起使用。

类项目:

代码语言:javascript
复制
    public class Item {          
      public String x;
      public Integer y;        
      public Integer z;
    }

类Main:

代码语言:javascript
复制
    public class Main {

      public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
        NumberDeserializers numberDeserializers = new NumberDeserializers();

        XmlMapper xmlMapper = new XmlMapper();    
        xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        // create custom-serialization
        XmlSerializerProvider provider = new XmlSerializerProvider(new XmlRootNameLookup());
        provider.setNullValueSerializer(new MyNullSerializer());
        xmlMapper.setSerializerProvider(provider);

        // create custom deserialization
        SimpleModule myModule = new SimpleModule("Module", new Version(1, 9, 10, "FINAL"));    
        myModule.addDeserializer(String.class, new NullableDeserializer(new StringDeserializer()));            
        myModule.addDeserializer(Number.class, new NullableDeserializer(numberDeserializers.find(Integer.class, Integer.class.getName())));
        myModule.addDeserializer(Float.class, new NullableDeserializer(numberDeserializers.find(Float.class, Float.class.getName())));

        xmlMapper.registerModule(myModule);  

        // deserialize
        Item value = xmlMapper.readValue(
            "<item xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ><a></a><x xsi:nil=\"true\"></x><y/><z>13</z></item>", 
            Item.class);

        // serialize
        String xml = xmlMapper.writeValueAsString(value); 
        System.out.println(xml);
      }
    }

MyNullSerializer类:

代码语言:javascript
复制
    public class MyNullSerializer extends JsonSerializer<Object> {
      @Override
      public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
        ToXmlGenerator xGen = (ToXmlGenerator) jgen;

        xGen.writeStartObject();
        try {
          xGen.getStaxWriter().writeAttribute("xsi:nil", "true");
        } catch (Exception e){
          e.printStackTrace();
        }
        xGen.writeEndObject();    
      }
    }

MyNullDeserializer类:

代码语言:javascript
复制
    public class MyNullDeserializer extends JsonDeserializer {

      private JsonDeserializer delegate; 

      public MyNullDeserializer(JsonDeserializer delegate){
        this.delegate = delegate;
      }

      @Override
      public Object deserialize(JsonParser jp, DeserializationContext ctxt)
          throws IOException, JsonProcessingException {

        FromXmlParser fxp = (FromXmlParser) jp;

        boolean isNil = false;

        XMLStreamReader reader = fxp.getStaxReader();
        if (reader.isStartElement()){
          if (reader.getAttributeCount() > 0){
            String atVal = reader.getAttributeValue("http://www.w3.org/2001/XMLSchema-instance", "nil");
            if (atVal != null){
              if (Boolean.parseBoolean(atVal) == true){
                isNil = true;
              }
            }
          }
        }

        Object value = null;
        if (isNil == false){
          value = delegate.deserialize(jp, ctxt);
        } else {
          jp.getValueAsString(); // move forward
        }
        return value;
      }

    }
票数 3
EN

Stack Overflow用户

发布于 2021-03-18 14:15:40

我对rnd的工作进行了扩展,因为它为所有字段启用了该功能,而不仅仅是其中的一部分。

这是一个您将添加到绑定中的模块,如下所示:

代码语言:javascript
复制
XmlMapper mapper = new XmlMapper();
    
XmlSerializerProvider provider = new XmlSerializerProvider(new XmlRootNameLookup());
provider.setNullValueSerializer(new NullSerializer());
mapper.setSerializerProvider(provider);
mapper.registerModule(new NullPointerModule());

NullPointerModule实现了自己的自定义序列化程序,以传递当前字段自检所需的属性。

NullPointerModule.java:

代码语言:javascript
复制
public class NullPointerModule extends SimpleModule implements java.io.Serializable {
    private static final long serialVersionUID = 1L;

    @Override
    public void setupModule(SetupContext context) {
        // Need to modify BeanDeserializer, BeanSerializer that are used
        context.addBeanSerializerModifier(new XmlBeanSerializerModifier() {
            @Override
            public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
                for (int i = 0, len = beanProperties.size(); i < len; ++i) {
                    BeanPropertyWriter bpw = beanProperties.get(i);
                    if (bpw.getClass().equals(BeanPropertyWriter.class)) {
                        beanProperties.set(i, new NullCheckedBeanPropertyWriter(bpw));
                    }
                }
                return beanProperties;
            }
        });
        super.setupModule(context);
    }

}

接下来是实际的NullSerializer,它接受属性编写器并确定字段是否需要nil字段。

NullSerializer.java:

代码语言:javascript
复制
public class NullSerializer extends JsonSerializer<Object> {

    @SuppressWarnings("unused")
    public void serializeWithProperty(BeanPropertyWriter propertyWriter, Object value, JsonGenerator jgen, SerializerProvider provider) {
        ToXmlGenerator xGen = (ToXmlGenerator) jgen;
        XmlElement annotation = null;

        if (propertyWriter != null) {
            AnnotatedMember member = propertyWriter.getMember();
            annotation = member.getAnnotation(XmlElement.class);
        }

        try {
            if (annotation != null) {
                if (annotation.nillable()) {
                    xGen.writeStartObject();
                    XMLStreamWriter staxWriter = xGen.getStaxWriter();

                    staxWriter.writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
                    staxWriter.writeAttribute("xsi:nil", "true");
                    xGen.writeEndObject();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
        serializeWithProperty(null, value, jgen, provider);
    }
}

最后是propertyWriters的覆盖。这是一个小技巧,因为如果属性编写器本身被另一个模块中的另一个类替换,这可能会失败。

NullCheckedBeanPropertyWriter.java:

代码语言:javascript
复制
public class NullCheckedBeanPropertyWriter extends BeanPropertyWriter {
    public NullCheckedBeanPropertyWriter(BeanPropertyWriter base) {
        super(base);
    }

    @Override
    public void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception {
        final Object value = (_accessorMethod == null) ? _field.get(bean)
                : _accessorMethod.invoke(bean);

        // Null handling is bit different, check that first
        if (value == null) {
            if (_nullSerializer != null) {
                gen.writeFieldName(_name);
                if (_nullSerializer instanceof NullSerializer) {
                    NullSerializer nullSerializer = (NullSerializer) _nullSerializer;
                    nullSerializer.serializeWithProperty(this, bean, gen, prov);
                    return;
                }
                _nullSerializer.serialize(null, gen, prov);
            }
            return;
        }
        super.serializeAsField(bean, gen, prov);
    }
}

然后可以使用@XmlElement(nillable=true)添加这些字段,使其符合您的需要。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21002930

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档