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 to Json serialization is not mapping the data properly #229

Closed
Krishnamohan10 opened this issue Apr 21, 2017 · 10 comments
Closed

XML to Json serialization is not mapping the data properly #229

Krishnamohan10 opened this issue Apr 21, 2017 · 10 comments
Milestone

Comments

@Krishnamohan10
Copy link

I have some list months in the row tags in a XML format. But while mapping the data to Json it is not mapping properly. Please check below for the reference.

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;

public class XML2Json {

	public static void main(String[] args) throws JsonProcessingException, IOException {

		String xml = "<root><months><row>Apr 2013</row><row>May 2013</row><row>Jun 2013</row><row>Jul 2013</row><row>Aug 2013</row></months></root>";

		XmlMapper xmlMapper = new XmlMapper();
		JsonNode node = xmlMapper.readTree(xml.getBytes());

		ObjectMapper jsonMapper = new ObjectMapper();
		String json = jsonMapper.writeValueAsString(node);

		System.out.println(json);
	}
}

The output for the above code is:

  "months": {
     "row": "Aug 2013"
   }
@capey0
Copy link

capey0 commented May 16, 2017

I get the same kind of thing from this. Not only does it not build a JSON array as it should, it completely loses the top level tag.

String xmlX = "<top><hdr>head</hdr><recs><rec><fn>aa</fn><il>bb</il><ln>cc</ln></rec><rec><fn>dd</fn><il/><ln>ee</ln></rec><rec><fn>dd</fn><il></il><ln>ee</ln></rec></recs></top>";
JsonNode outJSON = null;
ObjectMapper om = new ObjectMapper();
XmlMapper xM = new XmlMapper();

try {
	System.out.println("Incoming XML: " + xmlX);
	outJSON = om.readTree(om.writeValueAsString(xM.readTree(xmlX.getBytes())));
	System.out.println("Outgoing JSON: " + om.writeValueAsString(outJSON));
}
catch (Exception e) {
}


=====================
Here is the output:
=====================
Incoming XML: <top><hdr>head</hdr><recs><rec><fn>aa</fn><il>bb</il><ln>cc</ln></rec><rec><fn>dd</fn><il/><ln>ee</ln></rec><rec><fn>dd</fn><il></il><ln>ee</ln></rec></recs></top>
Outgoing JSON: {"hdr":"head","recs":{"rec":{"fn":"dd","il":null,"ln":"ee"}}}

By the way I am using Java 8 and have the following libraries:

core 2.8.8
databind 2.8.8
annotations 2.8.0
dataformat-xml 2.8.8
stax2-api 4.0.0
woodstox core asl 4.4.1

Do I have a library mismatch perhaps?

@shawnweeks
Copy link

This issue still exists with 2.9.3. I'm trying to migrate from json.org to jackson and the output of the conversion is incomplete.

@cowtowncoder
Copy link
Member

cowtowncoder commented Jan 23, 2018

Code works exactly as expected; there will not be "fixes". I will explain why.

  1. Tree Model (JsonNode) is not fully supported by module: and in particular, there is no real way to reliably tell apart expected Array and Object from XML input: XML only has elements and attributes. Databind can infer distinction from Java type (array, Collection). Tree Model can only assume Object.
  2. XML only allows single root, and this element represents Object container which in JSON would be pair of { and }.

From this I would strongly suggest that attempts to directly convert between XML and JSON using Tree Model is a bad idea. It is fine to convert from XML to POJO to JSON, or vice versa -- this will retain enough metadata to allow for proper conceptual conversion.
Fundamental problem here is not Jackson, or its handling, but rather that logical data model in XML is quite different from JSON and it simply can not (and should) be directly converted. It will not work.

@shawnweeks
Copy link

The problem is the json.org library does the conversion successfully in the examples I'm working with but the license isn't usable on our project and all the stack overflow posts point to Jackson as the only alternative. XLST is an alternative but i've been trying to avoid going down that path.

@cowtowncoder
Copy link
Member

@absolutesantaja one common case where things get wrong quickly is the case of "one element is Object; two or more repeated is Array" logic. This usually causes problems by converting what should be 1-value into Object/Map.

But as to converting from logic used by json.org it would be doable using Streaming API (creating JsonParser -- actually sub-class, FromXmlParser but usually base API sufficient).
That is some extra work but possibly worth the hassle. Parser would expose all elements, including ones that would be lost as duplicates. And then builder could create whatever data structure is needed, including JsonNode -- taking into account necessary coercion for duplicates, after establishing there is more than one instance of what seems like same property.

One thing that could be done for Jackson 3.0 -- and I'll make note of this as an idea -- would be to have separate XML Tree Model (XmlNode) which could implement same base interfaces (TreeNode, essentially), but allow duplicates, and also allow coercion into Arrays using common heuristics. I don't know if that should occur when reading, or as output/conversion option.

Since it seems there is a lot of demand for something like this I think it should be tackled in some form for Jackson 3.x. It is tricky challenge due to JSON/XML data model impedance... but worth tackling I think.

@Adiqq
Copy link

Adiqq commented Nov 19, 2018

I'd like to add that

Code works exactly as expected; there will not be "fixes".

Does not solve existing problem. We have problem here that might be hard to solve due to technical problems, but take perspective of end-user using this library.
I just want to convert XML to JSON, with some constraints, I don't want creating any POJO, because in most cases I will not know structure of incoming XML. In this case there might be some configurable guess, how it should be mapped. Additionaly I can provide XSD file for well-defined mapping for specific case. I also want to keep root tag from XML in result JSON. I might care for edge cases later, once I can solve my initial problem.

Now, what solution do I have right now, without studying intrinsics of Jackson and this XML extension for it?

@Adiqq
Copy link

Adiqq commented Nov 21, 2018

I prepared small Kotlin library to overcome problems mentioned in this issue. It offers naive implementation to overcome problem with missing root tag and it maps multiple child elements with the same name into a array.

@Cosmos19
Copy link

I land up with the same scenario today. It would be great if we have any workaround or solution for this usecase. I cant fall back from Jackson because the amount of work i put to use this high.

Thanks in advance.

@cowtowncoder cowtowncoder added the will-not-fix Issue for which there is no plan to fix as described or requested label May 20, 2020
@cowtowncoder
Copy link
Member

As things are, I will close this as "work as intended" just because JsonNode use is not supported (and issue with repeated elements) is mentioned. This does not mean that I don't think there is room for improvement, but rather that there needs to be separate issue(s) for specifically improving behavior in certain way. I think some already exist. Ideas include:

  1. Separate new Xml-specified tree/node model, not based on JsonNode (but might extend TreeNode if that matters)
  2. Alternate handling mode in which repeated elements read are used to "convert" ObjectNode into ArrayNode (would probably -- I will actually file jackson-databind issue for that.

@cowtowncoder
Copy link
Member

For what it is worth, this ultimately became #403 which is (2) from above: it will be included in 2.12.0.

@cowtowncoder cowtowncoder removed the will-not-fix Issue for which there is no plan to fix as described or requested label May 21, 2020
@cowtowncoder cowtowncoder added this to the 2.12.0 milestone May 21, 2020
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

6 participants