Синтаксический анализ фрагментов документа с помощью lift-json

#json #scala #lift #lift-json

#json #scala #lift #lift-json

Вопрос:

Я пытаюсь разобрать документ JSON с помощью lift-json, когда я могу не знать точную структуру и порядок документа, который я анализирую. Документ содержит список «объектов», все они организованы в разделы для данного типа объекта, причем каждый раздел назван в соответствии с этим типом. Я поиграл с различными способами перебора типов, сопоставления с шаблоном по имени типа, а затем попытался получить этот список объектов, но, похоже, это никогда не работает должным образом. Я либо получаю пустой список, либо сообщение об ошибке о невозможности найти подходящий фрагмент JSON для сопоставления с моими классами case.

Вот некоторый (почти псевдо) код, который настолько близок, насколько я смог:

 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];
    }
}
  

«адреса», «имена» и «электронная почта» могут располагаться в любом порядке внутри «запросов», и их может быть разное количество.

В конце я хочу иметь возможность извлекать списки объектов для соответствующего списка типов, а затем, после завершения синтаксического анализа, передавать различные списки объектов соответствующему методу.

Итак, вопрос в следующем: как я могу выполнить разбор на классы case в lift-json, если я заранее не знаю, какой будет полная структура документа.

Ответ №1:

Вы были очень близки, это работает на repl:

(Обновлено)

 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)
  }
}
  

Идея в том, что foreach «удаляет» список, который заключает в себе каждый «объект», поэтому мы вызываем typesQuery.запросы.extract, чтобы помочь классам case соответствовать нашему проанализированному json

Комментарии:

1. Хм, есть ли способ избежать JObject(Список(поле.. шум? Из-за этого то, что, по моему мнению, должно быть очень простым и прямолинейным фрагментом кода, выглядит действительно беспорядочно.

2. Похоже, что эта версия выдает ошибку net.liftweb.json.MappingException: No usable value for addresses , но я понимаю, к чему вы клоните.

3. используете ли вы последнюю версию lift-json? Я использую 2.4-M4 (2.4-M5 является последней версией.

4. Да, это работает, у меня была опечатка в моем файле JSON на моей стороне. Спасибо!