9

For a XML snippet like this:

val fruits =
<fruits>
  <fruit>
    <name>apple</name>
    <taste>ok</taste>
  </fruit>
  <fruit>
    <name>banana</name>
    <taste>better</taste>
  </fruit>
</fruits>

doing something like:

fruits \\ "fruit"

will return a sequence of type scala.xml.NodeSeq with all the fruits and sub nodes inside.

What is the best way to convert this to a list of JSON objects? I'm trying to send my list of fruits back to a browser. I had a look at scala.util.parsing.json.JSONObject and scala.util.parsing.json.JSONArray, but I don't know how to get from NodeSeq to anyone of the latter.

If at all possible, I would love to see how it's done with plain Scala code.

3 Answers 3

17

This might be relevant. Here is my solution using spray-json:

import scala.xml._
import cc.spray.json._
import cc.spray.json.DefaultJsonProtocol._

implicit object NodeFormat extends JsonFormat[Node] {
  def write(node: Node) =
    if (node.child.count(_.isInstanceOf[Text]) == 1)
      JsString(node.text)
    else
      JsObject(node.child.collect {
        case e: Elem => e.label -> write(e)
      }: _*)

  def read(jsValue: JsValue) = null // not implemented
}

val fruits =
  <fruits>
    <fruit>
      <name>apple</name>
      <taste>
        <sweet>true</sweet>
        <juicy>true</juicy>
      </taste>
    </fruit>
    <fruit>
      <name>banana</name>
      <taste>better</taste>
    </fruit>
  </fruits>

val json = """[{"name":"apple","taste":{"sweet":"true","juicy":"true"}},{"name":"banana","taste":"better"}]"""

assert((fruits \\ "fruit").toSeq.toJson.toString == json)
Sign up to request clarification or add additional context in comments.

7 Comments

This looks great, but your sample does not run. I get the following: error: not found: value JsField.
@JacobusR Oops, still using 1.0.1 version of spray-json. There is indeed no JsField class in 1.1.0. Replaced it with a tuple.
Works like a charm, thanks. Always lovely to get a runnable bit of code, rather than just a snippet (+1 for that :-).
FYI SprayJson has been recently updated, looks like JsonFormat has moved
A JsonWriter is more appropriate here as it means you don't need to have a dangling unimplemented read.
|
3

org.json4s makes this pretty simple:

import org.json4s.Xml.toJson

val fruits =
  <fruits>
    <fruit>
      <name>apple</name>
      <taste>
        <sweet>true</sweet>
        <juicy>true</juicy>
      </taste>
    </fruit>
    <fruit>
      <name>banana</name>
      <taste>better</taste>
    </fruit>
  </fruits>

println(toJson(fruits))

Comments

2

I think you should use ScalaXB to turn the XML into scala classes and then write the appropriate toJson bits to output Json.

Should work a treat.

1 Comment

The problem with ScalaXB is that it requires XML schema

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.