Frage

I'm trying to parse a JSON document with lift-json when I may not know the exact structure and order of the document that I'm parsing. The document contains list of "objects", all organized into sections for that object type with each section named for that type. I've played around with various ways to loop over the types, pattern-matching on the type name and then trying to get that list of objects out but it never seems to work properly. I either get a blank list or an error about not being able to find the proper JSON chunk to map to my case classes.

Here's some (almost pseudo) code that is as close as I've come:

case class TypesQueries(queries: Map[String, JValue]);

case class AddressQueries(addresses: List[AddressQuery]);
case class AddressQuery(street: String, city: String, state: String, zip: Int)

case class NameQueries(names: List[NameQuery]);
case class NameQuery(firstName: String, lastName: String);

case class EmailQueries(emails: List[EmailQuery]);
case class EmailQuery(emailAddress: String);

val jsonData = parse("""{
    "queries" : {
        "addresses" : [
            {
                "street" : "1234 Main St.",
                "city" : "New York",
                "state" : "New York",
                "zip" : 12345
            },
            {
                "street" : "9876 Broadway Blvd.",
                "city" : "Chicago",
                "state" : "IL",
                "zip" : 23456
            }
        ],
        "names": [
            {
                "firstName" : "John",
                "lastName" : "Doe"
            }
        ],
        "emails" : [
            {
                "emailAddress" : "john.doe@gmail.com"
            },
            {
                "emailAddress" : "david.smith@gmail.com"
            }
        ]
    }
}""");


val typesQuery = parse(jsonData).extract[TypesQueries];

typesQuery.queries.foreach { case(queryType, queryDefinition) =>
    queryType match {
        case "addresses" =>
            // These extract methods do not work.
            val addressQueries = queryDefinition.extract[AddressQueries];
        case "names" =>
            // These extract methods do not work.
            val nameQueries = queryDefinition.extract[NameQueries];
        case "emails" =>
            // These extract methods do not work.
            val emailQueries = queryDefinition.extract[EmailQueries];
    }
}

"addresses", "names" and "email" may come in any order inside "queries" and there may be a variable number of them.

In the end, I want to be able to extract lists of objects for the respective list of types and then, once the parsing is complete, pass the various lists of objects to the appropriate method.

So, the question is: How can I parse into case classes in lift-json if I do not know what the complete document structure will be ahead of time.

War es hilfreich?

Lösung

You were very close, this works on the repl:

(Updated)

typesQuery.queries.foreach { 
  case(queryType, queryDefinition) => queryType match {
    case "addresses" => val addressQueries = typesQuery.queries.extract[AddressQueries]; println(addressQueries)
    case "names" => val nameQueries = typesQuery.queries.extract[NameQueries]; println(nameQueries)
    case "emails" => val emailQueries = typesQuery.queries.extract[EmailQueries]; println(emailQueries)
  }
}

The idea is that the foreach "removes" the list that encloses each "object", so we call typesQuery.queries.extract to help the case classes match our parsed json

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top