【问题标题】:JAXB: How to customize Xml serialization of double fieldsJAXB:如何自定义双字段的 Xml 序列化
【发布时间】:2011-05-08 02:03:07
【问题描述】:

我有一个遗留类,有很多公共双字段。所有双字段都用Double.MAX_VALUE 初始化,表示它们是空的。 (遗留序列化被编码为忽略字段并且如果字段等于Double.MAX_VALUE则不序列化)。

我们现在正在尝试使用 JAXB Marshaller 将此类序列化为 Xml。它工作正常,除了我们要防止为等于Double.MAX_VALUE 的字段生成 Xml。

我们没有使用单独的 JAXB 模式,只是用各种 javax.xml.bind.annotation 注释标记我们的类。如果使用架构,您可以添加 <javaType> 元素来指定自定义 DataType 转换器。有没有办法使用注释或以编程方式做到这一点?

尝试以下推荐的方法后,我仍然无法获得XmlAdapter

@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(value=EmptyDoubleValueHandler.class, type=Double.class), @XmlJavaTypeAdapter(value=EmptyDoubleValueHandler.class, type=double.class)})
package tta.penstock.data.iserver;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;

我的顶级类是:tta.penstock.data.iserver.OrderBlotter,其中包含一个扩展 com.eztech.OrderResponse 的 tta.penstock.data.iserver.OrderResponseWrappers 列表。所有双字段都包含在com.eztech.OrderResponse中。

我的单元测试代码执行以下操作:

JAXBContext context = JAXBContext.newInstance(new Class[] { OrderBlotter.class, OrderResponseWrapper.class, OrderResponse.class});

Marshaller marshaller = context.createMarshaller();
StringWriter stringWriter = new StringWriter();
marshaller.marshal(blotter, stringWriter);
System.out.println("result xml=\n" + stringWriter.toString());

XmlAdapter 仍然无法处理双精度值。我知道我缺少一些基本的东西,但我不确定它是什么。

【问题讨论】:

    标签: java jaxb xml-serialization


    【解决方案1】:

    您可以使用 XmlAdapter:

    XmlAdapter

    package example;
    
    import javax.xml.bind.annotation.adapters.XmlAdapter;
    
    public class DoubleAdapter extends XmlAdapter<Double, Double>{
    
        @Override
        public Double unmarshal(Double v) throws Exception {
            return v;
        }
    
        @Override
        public Double marshal(Double v) throws Exception {
           if(Double.MAX_VALUE == v) {
               return null;
           } else {
               return v;
           }
        }
    
    }
    

    模型对象

    package example;
    
    import javax.xml.bind.annotation.XmlRootElement;
    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    
    @XmlRootElement
    public class Root {
    
        @XmlJavaTypeAdapter(DoubleAdapter.class)
        public Double maxDouble = Double.MAX_VALUE;
    
        @XmlJavaTypeAdapter(DoubleAdapter.class)
        public Double aDouble = 123d;
    
    }
    

    演示代码

    package example;
    
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.Marshaller;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            JAXBContext jc = JAXBContext.newInstance(Root.class);
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(new Root(), System.out);
        }
    
    }
    

    更新

    StaxMan 的建议很好。如果您指定以下包级别注释,则可以避免单独注释所有 Double 属性的需要

    package-info.java

    @XmlJavaTypeAdapters({
        @XmlJavaTypeAdapter(type=Double.class, value=DoubleAdapter.class)
    })
    package example;
    
    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
    

    【讨论】:

    • 我正在研究这种方法。问题是在遗留类中标记所有的双字段是有问题的。我正在寻找一个全局“钩子”,我们可以在其中指定或放置您上面列出的适配器类型。因此,即“对于此类中的每个双字段,请使用此 XmlAdapter”。
    • 您还可以为包添加 @XmlAdapter 注释(package-info.java 可以包含注释!)——查看 java 文档。这可能使这种方法可行
    • 我一直在尝试这种方法,这似乎是需要的。但似乎我放在那里的 XmlJavaTypeAdapter 注释在序列化期间没有被拾取。我认为这可能是因为这些字段包含在另一个包(我们项目之外)中定义的类中。但实际上,我不确定为什么它没有被捡起。
    • 只要这些类包含在您的 JAXBContext 中就可以了。您可能还想查看 EclipseLink JAXB (MOXy),我是技术主管:eclipse.org/eclipselink/moxy.php
    • 我已经尝试过包符号方法,但 XmlAdapter 没有被拾取。涉及的类:
    【解决方案2】:

    写一个返回null的getter,而不是Double.MAX_VALUE? (如果类型是'double',需要先将其更改为'Double',以允许空值)。 由于默认情况下 JAXB 会忽略写入空值,因此应该可以实现您想要做的事情。这假设您可以修改有问题的遗留类。

    【讨论】:

    • 感谢您的建议。不幸的是,遗留类不能轻易修改(并且有“百万”公共双字段需要包装)。正在寻找更简单的出路...
    猜你喜欢
    • 1970-01-01
    • 2019-06-26
    • 2010-10-05
    • 2016-02-12
    • 2010-11-27
    • 1970-01-01
    • 2010-10-13
    • 2012-06-08
    • 1970-01-01
    相关资源
    最近更新 更多