Can I use the Scala lift-json library to parse a JSON into a Map?

tommy chheng picture tommy chheng · Oct 1, 2010 · Viewed 7.2k times · Source

Is there a way to use the lift-json library's JObject class to act like a Map?

For example:

val json = """
{ "_id" : { "$oid" : "4ca63596ae65a71dd376938e"} , "foo" : "bar" , "size" : 5}
"""

val record = JsonParser.parse(json)
record: net.liftweb.json.JsonAST.JValue = JObject(List(JField(_id,JObject(List(JField($oid,JString(4ca63596ae65a71dd376938e))))), JField(foo,JString(bar)), JField(size,JInt(5))))

</code>

I would have expected record("foo") to return "bar"

I noticed a values function and it prints out a Map but the actual object is a JValue.this.Values?

scala> record.values res43: record.Values = Map((_id,Map($oid -> 4ca63596ae65a71dd376938e)), (foo,bar), (size,5))

scala> record.values("foo") :12: error: record.values of type record.Values does not take parameters record.values("foo")

There are examples with the lift-json library extracting a case class but in this case, I don't know the json schema in advance.

Answer

Alexey Romanov picture Alexey Romanov · Oct 1, 2010

If you look at the implementation, you'll see

case class JObject(obj: List[JField]) extends JValue {
  type Values = Map[String, Any]
  def values = Map() ++ obj.map(_.values.asInstanceOf[(String, Any)]) // FIXME compiler fails if cast is removed
}

So this should work:

record.values.asInstanceOf[Map[String, Any]]("foo")

You could also try

record.values.apply("foo")