Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XML Empty tag to Empty string in the object during xml deserialization #162

Closed
thefalconfeat opened this issue Oct 2, 2015 · 18 comments
Closed
Milestone

Comments

@thefalconfeat
Copy link

I am using jackson-dataformat-xml:2.6.2

If an empty tag is available in the xml and the respective field in the object is a string, it would be nice to have jackson populate the field with empty string rather than with null value.

Ex:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(
        name = "",
        propOrder = {"first", "last"}
)
@XmlRootElement(
        name = "name"
)
public class Name {
private String first;
private String last;
}

xml:

<name>
<first>Ryan</first>
<last></last>
</name>

mapper creation:

new XmlMapper(XMLInputFactory2.newFactory(), XMLOutputFactory2.newFactory());

I would expect

Name name = mapper.readValue(xml, Name.class)

name.getLast().equals("") to return true but name.getLast() ends up being null.

Any help would be appreciated.

@cowtowncoder
Copy link
Member

Yes I can reproduce this. It is a tricky problem to solve but I added a failing unit test so that hopefully it may be resolved in future.

In the meantime a work-around would be to add explicit setLast() that can convert null into empty String (and perhaps also pre-initialize last as empty string in constructor.

@cowtowncoder
Copy link
Member

I have some ideas as to how this could be implemented; but actual fix will need to wait until 2.8 unfortunately, as some API changes will be needed.

@RobinAllen
Copy link

I'm also facing what I think is the same issue.
In my case (simplified here to just the basic problem), I'm reading xml which defines a 'Thing's state as A or B:

State A : "<Thing><A /></Thing>"
State B : "<Thing><B /></Thing>"

Both A and B are defined in XSD as being 'xsd:string' with max length 0 characters. 'Thing' is a complextype, defined as being xsd:choice between element A or element B. They are intended to have no content; it is purely the presence or absence of the empty element which declares which state we are in. Sadly I don't have control over the interface to be able to change the logic. I have to live with this XML interface.

In Java, the POJO generated from XSD has String fields 'a' and 'b'.

If I serialize from POJO to XML I have no problem, but the trouble comes when I try to deserialize again.

If I deserialize "<Thing><A /></Thing>", then I want to end up with [ a="", b=null ]
If I deserialize "<Thing><B /></Thing>", then I want to end up with [ a=null, b="" ]
But whichever input I deserialize, I get the same results: [ a=null, b=null ]

So you see, I'm unable to detect WHICH empty element was present, which leaves me unable to know which state it was in.

If I could submit some content inside the A / B, even just a space character, then it would deserialize properly. But I can't validly submit content inside the A / B element, because that would not be acceptable according to the XSD (max length 0 characters).

I see this as a fault, really, because dataformat-xml cannot read back in the xml which it itself has outputted. If I serialize a Thing from POJO to XML string and then deserialize back to POJO again, I don't get back in the same object I wrote out. (Quoting the readme page: "What should be guaranteed is that any XML written using this module must be readable using module as well")

@cowtowncoder
Copy link
Member

@RobinAllen This is indeed problematic, but consider that without mandating use of XML Schema's nillable, there really is nothing to definitely differentiate empty String from null.

Anyway, I do hope that with 2.8 (to be worked on next now that 2.7.0 is ready to release) we can at least ensure that empty element, for String valued property, will become "". And total absence of element would in that case remain null. And finally, maybe nullability with XML schema can be eventually supported as well, for explicit nulls.

@manueljordan
Copy link

Hello

what is the status of this situation?

I am working with Jackson 2.8.2 and seems this situation is reflected until now in:
Spring Rest & Jackson: Empty values are transformed in Null values in XML transformation

Thanks

@cowtowncoder
Copy link
Member

@manueljordan If there is progress, there will be update here. I have not worked on this, and am unlikely to have much time in near future.

@manueljordan
Copy link

@cowtowncoder thanks by the quick reply. I understand. The important is it was reported. Yes, take your time, I know you are busy. Meanwhile I have turned around this situation in other way.

@jlous
Copy link

jlous commented Dec 13, 2016

Eagerly awaiting this! Would a pull-request make any difference in ETA in an official release?

oistein pushed a commit to oistein/jackson-dataformat-xml that referenced this issue Dec 22, 2016
@jlous
Copy link

jlous commented Jan 3, 2017

Any idea when the PR might be merged if approved?

@manueljordan
Copy link

What is needed to approve the PR?

@oistein
Copy link

oistein commented Mar 3, 2017

Yeah, what is stopping this?

@zhoulei-patsnap
Copy link

zhoulei-patsnap commented Apr 7, 2017

@cowtowncoder
Hello,what is the status of this situation? Which is version that the bug is fiexed?

@jhaber
Copy link

jhaber commented May 24, 2017

This is a pretty painful issue to run into, but after a lot of not-so-fun experimentation I came up with two different workarounds that I think should handle most use-cases. You can check them out here

cowtowncoder added a commit that referenced this issue Jun 21, 2017
Fix for #162 (XML Empty tag to Empty string)
@cowtowncoder cowtowncoder added this to the 2.9.0 milestone Jun 21, 2017
@cowtowncoder
Copy link
Member

Quick note: related to #209, Jackson 2.9 SHOULD allow use of:

@JsonSetter(nulls=Nulls.AS_EMPTY)
public String value;

to basically coerce null value into empty String (or one of alternatives; skip assignment to leave as default, throw exception). It's via databind feature:

FasterXML/jackson-databind#1402

I will test that this works, and if so, mark this as closed.

@cowtowncoder
Copy link
Member

Ok. Hmmh. So, good and bad news.

Good news: woth empty tags, works as expected.

Bad news: open+start, without even intervening space (so simple <value></value>) does NOT work as expected. Can not remember if (... and, how?) there was intentional checking to effect different handling. But XML semantics should not differ between two representations.

@cowtowncoder
Copy link
Member

So. Works as suggested with empty tag, in 2.9. And with ACCEPT_EMPTY_STRING_AS_NULL_OBJECT can make other cases work too.

In 3.0.0 will further work the same way for "split" empty tag (start+end).

@cowtowncoder cowtowncoder modified the milestones: 2.9.0, 2.9.6 May 5, 2018
@cowtowncoder
Copy link
Member

Note: some of the fixes to jackson-databind will go in 2.9.6. So above comments reflect to that upcoming version.

@itisvamsi
Copy link

Is there any fix for this which is available?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants