Thanks for the update Joni and sorry for not getting back sooner. I'll try the code change you've suggested. Should I open a bug for the final example?
Cheers Jono 2009/10/28 Joni Freeman <freeman.j...@gmail.com> > > Hi Jonathan, > > Current toJson conversion does not support this case very well. The > transformation rule is such that from each leaf XML element a JSON > field is generated. > > <stats>foo</stats> -> > "stats":"foo" > > And if that leaf element contains attributes we do not convert it > automatically to JSON object as you expected. Instead, another field > at same level is created: > > <stats count="0">foo</stats> -> > "stats":"foo" > "count":"0" > > In your case the leaf node is empty, therefore you will get a field > with null value: > > <stats count="0"></stats> -> > "stats":null > "count":"0" > > You can fix this for instance by postprocessing the generated JSON. In > this case it is a bit involved and verbose (example below fixes > 'stats' element, similar conversion is required for 'messages' > element): > > val json = toJson(xml1) map { > case JField("count", JString(count)) => JObject(JField("count", JInt > (count.toInt)) :: Nil) // lift to object > case JField("stats", _) => JNothing // remove null field > case x => x > } map { > case JField("count", x: JObject) => JField("stats", x) // rename > field "count" to "stats" > case x => x > } > > Note, the conversion rule which you expected is a perfectly valid > conversion too. The rationale behind the current rule is that it never > makes conversions which changes resulting JSON structure when > attributes are missing. It is therefore more predictable. This blog > post summarizes some other valid conversion rules > http://onwebdevelopment.blogspot.com/2008/05/converting-xml-to-json.html > > We could add support for other conversion rules if there's a strong > pressure to do so. But my current preference is to use a simple rule > and then handle corner cases using transformation pipelines (using > 'map' function). > > PS. The very last example you gave contains a bug which I try to nail > down today. XML is parsed differently when all elements are in same > line. Thanks for good examples! > > Cheers Joni > > On 28 loka, 09:24, Jonathan Ferguson <j...@spiralarm.com> wrote: > > Depending on the structure of the XML, attributes and child elements > > are being lost. This can be seen in example 4, where the attribute > > expiry_date and the child element status have been dropped. > > > > It would also appear when XML is being converted to JSON attributes > > are being flattened to elements. I'm not sure if this is expected or > > not, this can be seen in examples 1,2 & 3. The child > > element status with attribute count is converted to two attributes > > status with a value of null and count with the correct value. > > > > To test I added the following before the closing brace of > > XmlExamplesTest.scala in lift-json. > > > > Is this a bug or my error ? > > > > Cheers > > Jono > > > > P.S I've noticed this could be related to the thread "Possible lift- > > json bug in Xml.toJson" > http://groups.google.com/group/liftweb/browse_thread/thread/47c581d63... > > > > /*==== Test ====*/ > > > > import scala.xml.Node > > > > def xml2Json(xml:Node):String = { > > val json = toJson(xml) > > compact(render(json)) > > } > > > > "XML to JSON Example with multiple attributes, multiple nested > > elements " in { xml2Json(xml1) mustEqual expected1 } > > "XML to JSON Example with multiple attributes, multiple nested > > elements " in { xml2Json(xml2) mustEqual expected2 } > > "XML to JSON Example with one attribute, multiple nested elements > > " in { xml2Json(xml3) mustEqual expected3 } > > "XML to JSON Example with one attribute, one nested element " in > > { xml2Json(xml4) mustEqual expected4 } > > > > val xml1 = <message expiry_date="20091126" text="text" > > word="ant" self="me"><stats count="0"></stats><messages href="https:// > > domain.com/message/ant"></messages></message> > > val expected1 = """{"message":{"expiry_date": > > 20091126,"text":"text","word":"ant","self":"me","stats":{"count": > > 0},"messages":{"href":"https://domain.com/message/ant"}}}""" > > val actual1 = """{"message": > > > {"expiry_date":"20091126","word":"ant","text":"text","self":"me","stats":null,"count":"0","messages":null,"href":"https:// > > domain.com/message/ant"}}""" > > > > val xml2 = <message expiry_date="20091126" text="text" > > word="ant" self="me"><stats count="0"></stats><messages href="https:// > > domain.com/message/ant"></messages></message> > > val expected2 = """{"message":{"expiry_date": > > 20091126,"text":"text","word":"ant","self":"me","stats":{"count": > > 0},"messages":{"href":"https://domain.com/message/ant"}}}""" > > val actual2 = """{"message": > > > {"expiry_date":"20091126","word":"ant","text":"text","self":"me","stats":null,"count":"0","messages":null,"href":"https:// > > domain.com/message/ant"}}""" > > > > val xml3 = <message expiry_date="20091126"><stats count="0"></ > > stats><messages href="https://domain.com/message/ant"></messages></ > > message> > > val expected3 = """{"message":{"expiry_date":20091126,"stats": > > {"count":0},"messages":{"href":"https://domain.com/message/ant"}}}""" > > val actual3 = """{"message": > > > {"expiry_date":"20091126","stats":null,"count":"0","messages":null,"href":"https:// > > domain.com/message/ant"}}""" > > > > val xml4 = <message expiry_date="20091126"><stats count="0"></ > > stats></message> > > val expected4 = """{"message":{"expiry_date":20091126,"stats": > > {"count":0}}}""" > > val actual4 = """{"message":""}""" > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~----------~----~----~----~------~----~------~--~---