Posso usar a biblioteca Scala lift-json para analisar um JSON em um mapa?
Pergunta
Existe uma maneira de usar a classe JObject da biblioteca lift-json para agir como um mapa?
Por exemplo:
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>
Eu esperava que record("foo") retornasse "bar"
Notei uma função de valores e ela imprime um mapa, mas o objeto real é um 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")
Existem exemplos com a biblioteca lift-json extraindo uma classe de caso, mas neste caso, não conheço o esquema json com antecedência.
Solução
Se você olhar para a implementação, você verá
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
}
Então isso deve funcionar:
record.values.asInstanceOf[Map[String, Any]]("foo")
Você também pode tentar
record.values.apply("foo")
Outras dicas
JValue.Values é um tipo dependente de caminho.O que significa que se você segurar um JString, será uma String, ou se você tiver um JArray, será um List[Any].Se você tiver certeza de que o JSON analisado é um objeto JSON, poderá convertê-lo em um tipo adequado.
val record = JsonParser.parse(json).asInstanceOf[JObject]
Um tipo dependente de caminho para JObject é Map[String, Any], portanto:
scala> record.values("foo")
res0: Any = bar
Só por curiosidade, não é um pouco problemático se você não sabe o formato dos dados que vai analisar?
Observe que se seus dados contiverem (nome, descrição, idade) e a idade for opcional, você poderá ler esse JSON em:
case class Person(name: String, description: String, age: Option[Int])