java JAXB:如何自定义双字段的 Xml 序列化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4148192/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 05:02:01  来源:igfitidea点击:

JAXB: How to customize Xml serialization of double fields

javajaxbxml-serialization

提问by Sam Goldberg

I have a legacy class, with a lot of public double fields. All double fields are initialized with Double.MAX_VALUEto indicate that they are empty. (The legacy serialization is coded to ignore the field and not serialize if field is equals to Double.MAX_VALUE).

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

We are now trying to serialize this class to Xml using JAXB Marshaller. It is working fine, except that we want to prevent generating Xml for fields which equal Double.MAX_VALUE.

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

We aren't using a separate JAXB schema, just marking up our classes with various javax.xml.bind.annotationAnnotations. If a schema is used, you can add a <javaType>element to specify a custom DataType converter. Is there any way to do this using Annotations or programmatically?

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

After trying approach recommended below, I still can't get XmlAdapterpicked up:

在尝试了下面推荐的方法后,我仍然无法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;

My top level class is: tta.penstock.data.iserver.OrderBlotter, which contains a list of tta.penstock.data.iserver.OrderResponseWrappers which extends com.eztech.OrderResponse. All the double fields are contained in com.eztech.OrderResponse.

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

My unit test code does the following:

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

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());

But the double values still don't get handled by the XmlAdapter. I know I'm missing something basic, but I'm not sure what it is.

但是双值仍然没有被XmlAdapter. 我知道我缺少一些基本的东西,但我不确定它是什么。

回答by bdoughan

You could use an XmlAdapter:

您可以使用 XmlAdapter:

The 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;
       }
    }

}

The Model Object

模型对象

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;

}

Demo Code

演示代码

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);
    }

}

UPDATE

更新

StaxMan's suggestion is a good one. If you specify the following package level annotation you can avoid the need of individually annotating all the Double properties

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

package-info.java

包信息.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;

回答by StaxMan

Write a getter that returns null, instead of Double.MAX_VALUE? (if type is 'double', need to change it to 'Double' first, to allow nulls). Since JAXB by default ignores writing out of nulls, that should achieve what you are trying to do. This assumes you can modify legacy class in question.

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