简体   繁体   English

从JAXB强制转换null java.lang.Integer会产生0,而不是null

[英]Casting null java.lang.Integer from JAXB produces 0, not null

I have the following XML: 我有以下XML:

<person>
    <id/>
    <Identifier/>
    <Surname>TEST</Surname>
    <Forename1>TEST</Forename1>
    <Forename2/>
    <Title>MR</Title>
    <Gender>M</Gender>
</person>

Produced by serialising the following class: 通过序列化以下类产生:

package anonymised.packagename;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)

@XmlType(name = "", propOrder = {
    "Id",
    "Identifier",
    "Surname",
    "Forename1",
    "Forename2",
    "Title",
    "Sex"
})

@XmlRootElement(name = "person")
public class person{

    @XmlElement(name = "id", nillable=true)
    protected Integer Id;
    public Integer getId(){
        return Id;
    }

    public void setId(Integer value){
        this.Id = value;
    }

    @XmlElement(name = "Identifier", nillable=true)
    protected String Identifier;
    public String getIdentifier(){
        return Identifier;
    }

    public void setIdentifier(String value){
        this.Identifier = value;
    }

    @XmlElement(name = "Surname", nillable=true)
    protected String Surname;
    public String getSurname(){
        return Surname;
    }

    public void setSurname(String value){
        this.Surname = value;
    }

    @XmlElement(name = "Forename1", nillable=true)
    protected String Forename1;
    public String getForename1(){
        return Forename1;
    }

    public void setForename1(String value){
        this.Forename1 = value;
    }

    @XmlElement(name = "Forename2", nillable=true)
    protected String Forename2;
    public String getForename2(){
        return Forename2;
    }

    public void setForename2(String value){
        this.Forename2 = value;
    }

    @XmlElement(name = "Title", nillable=true)
    protected String Title;
    public String getTitle(){
        return Title;
    }

    public void setTitle(String value){
        this.Title = value;
    }

    @XmlElement(name = "Gender", nillable=true)
    protected String Gender;
    public String getGender(){
        return Gender;
    }

    public void setGender(String value){
        this.Gender = value;
    }
}

I used the "set" methods on the object and JAXB serialisation to produce the XML above, choosing java.lang.Integer objects precisely because they are nullable. 我使用对象上的“设置”方法和JAXB序列化生成上面的XML,正是由于它们是可空的,因此选择java.lang.Integer对象。

I then used the following code to deserialise the XML (represented by xmlString) back to the object: 然后,我使用以下代码将XML(由xmlString表示)反序列化回该对象:

DocumentBuilder builder = fac.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(xmlString)));
String className = "anonymised.packagename." + doc.getDocumentElement().getNodeName();
Class<?> c = Class.forName(className);
JAXBContext context = JAXBContext.newInstance(c);
Unmarshaller um = context.createUnmarshaller();
Object o = c.cast(um.unmarshal(new StringReader(xmlString)));

JAXBContext jbc = JAXBContext.newInstance(c);
Marshaller jm = jbc.createMarshaller();

jm.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

jm.marshal(o, new File("C:\\person.xml"));

Which produced the following XML file: 产生了以下XML文件:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
    <id>0</id>
    <Identifier/>
    <Surname>TEST</Surname>
    <Forename1>TEST</Forename1>
    <Forename2></Forename2>
    <Title>MR</Title>
    <Gender>M</Gender>
</person>

The java.lang.Integer that was null is now 0. How can this be? 现在为null的java.lang.Integer为0。这怎么可能? Judging by breakpoints, the change from null to 0 occurs during the casting process, but I can't figure out why exactly this is. 从断点来看,在转换过程中会发生从null到0的更改,但是我不知道为什么会这样。 Is there some kind of conversion to a simple int during the casting process? 在转换过程中是否有某种转换为简单int的方法? Is there a way to avoid this phenomenon? 有办法避免这种现象吗? I thought adding "nillable" to the XML Element declaration would help, but it hasn't. 我认为在XML Element声明中添加“ nillable”会有所帮助,但没有帮助。

JAXB doesn't consider any empty element to be a valid representation of null . JAXB认为任何空元素都不是null的有效表示形式。 If you introspect the indentifier property of type String you'll see it is "" after you unmarshal the empty element. 如果您indentifier String类型的indentifier属性进行内省,则在解组空元素后会看到它是""

The two valid representations of null are: null的两个有效表示形式是:

  1. Missing element, corresponds to minOccurs="0" in the XML Schema. 缺少的元素,对应于XML模式中的minOccurs="0" This is the default behaviour. 这是默认行为。
  2. xsi:nil="true" on the element. 元素上的xsi:nil="true" This corresponds to nillable="true" in the XML Schema. 这对应于XML架构中的nillable="true" If you annotate your property with @XmlElement(nillable=true) you will get this behaviour. 如果使用@XmlElement(nillable=true)注释属性,则将获得此行为。

UPDATE UPDATE

Thanks for your answer. 感谢您的回答。 On point 2, I have annotated my property with @XmlElement(nillable = true) in the class above, but I haven't got the behaviour you describe in my XML. 在第2点上,我在上面的类中用@XmlElement(nillable = true)注释了我的属性,但是我没有您在XML中描述的行为。 Does your answer mean that, in the production of any XML that should be null, the attribute xsi:nil needs to explicitly be set to true? 您的答案是否意味着在生成任何应该为null的XML时,需要将属性xsi:nil显式设置为true?

When you have @XmlElement(nillable=true) the expectation is that the corresponding XML element has the xsi:nil attribute set to true like the following: 当您拥有@XmlElement(nillable=true) ,期望的是相应的XML元素将xsi:nil属性设置为true ,如下所示:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
    <id xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
</person>

I'm happy with the idea that the Identifier element is an empty String, not null, but the id element, because it's an Integer should be null, not 0, right? 我对Identifier元素是一个空String而不是null而是id元素的想法感到满意,因为它是一个Integer应该为null而不是0,对吧?

You can definitely make that argument. 您绝对可以提出该论点。 With the JAXB RI if you change your Integer property to Long you will see the behaviour you are looking for. 使用JAXB RI,如果将Integer属性更改为Long您将看到所需的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用java.lang.Integer属性将空字符串传递给.tag会导致0(不为null) - Passing empty string to .tag with a java.lang.Integer attribute results in 0 (not null) 无法调用“PacienteService.findById(java.lang.Integer)”因为“this.service”是 null - Cannot invoke "PacienteService.findById(java.lang.Integer)" because "this.service" is null 获取ClassCastException:java.lang.Integer无法强制转换为java.lang.String错误 - Getting a ClassCastException: java.lang.Integer cannot be cast to java.lang.String error without casting Freemarker 调用 static java 方法来自 java.lang.ZA0FAEF0851B4194C46F46Z 方法 - Freemarker call static java method from java.lang.Integer 无法从java.lang.Integer转换为R - Cannot convert from java.lang.Integer to R 不支持从 DATE 到 java.lang.Integer 的转换 - Unsupported conversion from DATE to java.lang.Integer Hibernate HQL强制转换java.lang.ClassCastException:java.lang.Integer无法强制转换为java.lang.Long - Hibernate HQL casting java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long java.lang.Integer 的 Java 反序列化 - 异常 - Java Deserialization of java.lang.Integer - Exception java.lang.Integer内部代码中的一个问题 - A question in java.lang.Integer internal code java.lang.Integer无法转换为JSONObject - java.lang.Integer cannot be converted to JSONObject
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM