json4s icon indicating copy to clipboard operation
json4s copied to clipboard

convert xml to json

Open spongebobZ opened this issue 4 years ago • 2 comments

json4s version

3.7.0-M4

scala version

2.12.10

jdk version

1.8

I have one xml just like:

<Teacher id="1">
    <name>Jim</name>
    <contact phone="123456" id="2">
        <color>blue</color>
    </contact>
</Teacher>

When I convert this xml to json, it looks nice: {"Teacher":{"id":"1","name":"Jim","contact":{"phone":"123456","id":"2","color":"blue"}}}

But if I remove the "color" tag, just like:

<Teacher id="1">
    <name>Jim</name>
    <contact phone="123456" id="2"></contact>
</Teacher>

It would get this json result: {"Teacher":{"id":"1","name":"Jim","phone":"123456","id":"2"}} actually I think the "contact" tag should be Map structure

spongebobZ avatar May 19 '20 09:05 spongebobZ

@spongebobZ

First, there is no convention for converting XML to JSON This is why various libraries have their own implementations.

The implementation of Json4s is based on the following rules.

  • Merge child elements and attributes, if any, with the child elements and attributes
scala> val json = compact(render(toJson(<a b="1"><c>2</c></a>)))
val json: String = {"a":{"b":"1","c":"2"}}
  • If there is no child element and only attributes are present, then only attributes remain (the pattern pointed out here).
scala> val json = compact(render(toJson(<a b="1"></a>)))
val json: String = {"b":"1"}
  • Without both the child element and the attributes, only an empty character remains.
scala> val json = compact(render(toJson(<a></a>)))
val json: String = {"a":""}

That is, the presence or absence of child elements changes the hierarchy in which attributes are merged.

If the policy is not to change the idea of the hierarchy in which attributes are merged, and if you want to eliminate the loss of tags, it seems consistent to convert them as follows.

scala> val json = compact(render(toJson(<a b="1"></a>)))
val json: String = {"a":"", "b":"1"}

It's different from the solution originally noted, but in terms of consistency with other implementations, it looks like a good way to go.

Do you have an opinion?

magnolia-k avatar May 24 '20 06:05 magnolia-k

Note that the second pattern can be converted to the following using Perl's XML::Simple.

{"a":{"b":"1"}}

Also, the following pattern conversions are different from the Json4s-XML conversions.

xml

<a b="1">c</a>

json

{"a":{"b":"1","content":"c"}}
scala>val json = compact(render(toJson(<a b="1">c</a>)))
val json: String = {"a":"c","b":"1"}

The above pattern is converted to the following in Json4s-XML

Perl's XML::Simple uses a special key called 'content' to keep the hierarchical structure consistent after conversion.

This way of thinking is more consistent, and Json4s-XML should be supported in the same way, but there is a problem of backward compatibility, and it is desirable to use Json4s 4.0.0.

magnolia-k avatar May 24 '20 11:05 magnolia-k