Closed HenryYihengXu closed 10 months ago
Intent with Jackson XML module is that it should be able to read what it writes: so the XML structure created with XmlMapper.writeValue(myObject2)
should be readable with XmlMapper.readValue(xmlDoc, MyObject2.class)
.
If not, that is considered bug.
Package does not necessarily allow mapping different kinds of XML representations.
Then this should be a bug. I tried reading back what it writes. It's readable, but the deserialized object is different from the original one.
Here is the code:
@Test
void testJacksonXml2() throws IOException {
MyObject2 myObject2 = new MyObject2();
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.registerModule(new Jdk8Module());
xmlMapper.writeValue(new File("test-jackson.xml"), myObject2);
MyObject2 deserializedMyObject2 = xmlMapper.readValue(new File("test-jackson.xml"), MyObject2.class);
xmlMapper.writeValue(new File("deserialized-test-jackson.xml"), deserializedMyObject2);
assertThat(myObject2).isEqualTo(deserializedMyObject2);
}
The test is failing. And I checked "test-jackson.xml" and "deserialized-test-jackson.xml". They are indeed different. The former is just
<MyObject2>
<MyObject/>
</MyObject2>
but the later one is
<MyObject2>
<myObject>
<a>1</a>
</myObject>
</MyObject2>
Could you fix this bug? I would appreciate it!
That sounds like a bug then.
Unfortunately I doubt I have time to tackle this issue at this point. But if you or anyone else has time and interest, I can help get PR reviewed and so on.
One practical challenge here is that of testing, as the issue requires both XML module and JDK 8 datatype module -- neither of which should have dependency to the other.
But I think same problem would affect use of AtomicReference
type, too, and if reproducing the issue with it, test could be added in jackson-dataformat-xml
.
And fix, if any, would likely work for Optional
too as their handling is very similar internally.
Do you have an idea on how to fix it? I looked at your OptionalDeserializer, looks like it should deserialize to Optional.empty()
?
A major problem is that empty XML element can mean either "empty" value (like "" for java.lang.String
or, for POJOs, instance constructed with default constructor); OR null
value.
In this case I think you get "empty" Object, then wrapped in Optional
.
One way to force "null-ness" is to add xsi:nil
attribute like so:
<!-- NOTE: xmlns:xsi could be declared in parent to avoid using multiple times
-->
<MyObject2>
<MyObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" />
</MyObject2>
Ok, so, above xsi:nil
works. But to produce it on writing, you need to enable
ToXmlGenerator.Feature.WRITE_NULLS_AS_XSI_NIL
after which things work.
I don't see a working way to solve this problem in other way but I suggest you try this.
I have an object
then another object with an optional field of the object above
I serialize MyObject2 as
I got
I'm assuming a single
<xxx/>
denotes optional empty? Is this correct? Assume it is correct, I deserialize it asBut then I found the deserialized one is not Optional.empty. It seems to call the default constructor of MyObject so it has a = 1 in it. Do you know how should I actually deserialize Optional.empty?