2010-10-01 8 views
11

¿Hay alguna manera de utilizar la clase JObject de la biblioteca lift-json para actuar como un Mapa?¿Puedo usar la biblioteca Scala lift-json para analizar un JSON en un mapa?

Por ejemplo:

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> 

disco que yo hubiera esperado ("foo") para volver "barra"

me di cuenta de una función de los valores y se imprime un mapa, pero el objeto real es una 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")

Hay ejemplos con la biblioteca de elevación JSON extracción de una clase de caso, pero en este caso, no sé el esquema JSON con antelación.

+0

Esta es una respuesta relacionada para analizar mapa como un parámetro en una clases de casos http://stackoverflow.com/questions/5051290/deserializing-case-classes-with-mapstring-any-properties-with-lift-json/6310493#6310493 –

Respuesta

12

Si nos fijamos en la aplicación, 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 
} 

Así que esto debería funcionar:

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

También puede probar

record.values.apply("foo") 
+0

Gracias, el primero funciona, la segunda opción de usar apply () devuelve un error. Terminé usando el analizador de Java incorporado de scala. scala.util.parsing.json.JSON.parseFull (registro) devolverá Some (Map) or Some (List) –

7

JValue.Values ​​es una tipo dependiente de ruta. Lo que significa que si sostienes una JString será una Cadena, o si tienes una JArray será una Lista [Cualquiera]. Si está seguro de que el JSON que analiza es un objeto JSON, puede convertirlo a un tipo apropiado.

val record = JsonParser.parse(json).asInstanceOf[JObject] 

Un tipo dependiente de la trayectoria de jobject es un mapa [String, Cualquier], por lo tanto:

scala> record.values("foo")          
res0: Any = bar 

Sólo por curiosidad, ¿no es un poco problemático si usted no sabe la forma de datos que vas a analizar

Nota, si los datos contienen (nombre, descripción, edad) y la edad es opcional se puede leer que JSON en:

case class Person(name: String, description: String, age: Option[Int]) 
+0

Tengo un json que tiene una matriz de campos diferentes. Por ej. el primer documento puede tener (nombre, descripción, edad) pero el segundo documento solo puede tener (nombre, edad) especificado. Si utilizo el objeto Map de scala, solo puedo llamar a document.getOrElse ("foo", "") –

Cuestiones relacionadas