2015-02-16 1 views
0

Я ищу хорошую абстракцию для извлечения формы данных JSON (сейчас я использую json4s).Абстракция для извлечения данных из JSON в Scala

Предположим, у меня есть класс case A и данные в формате JSON.

case class A(a1: String, a2: String, a3: String) 

{"a1":"xxx", "a2": "yyy", "a3": "zzz"} 

Мне нужна функция для извлечения данных в формате JSON и возвращать A эти данные следующим образом:

val a: JValue => A = ... 

Я не хочу, чтобы написать функцию a с нуля. Я бы предпочел составить это из примитивных функций.

Например, я могу написать примитивную функцию для извлечения строки по имени поля:

val str: (String, JValue) => String = {(fieldName, jval) => ... } 

Теперь я хотел бы составить функцию a: JValue => A из str. Имеет ли это смысл ?

+0

Ну ... Я не уверен, что это актуально, но если вы используете PlayJson ..., то он предоставляет Scala Macros, чтобы выполнить эту работу очень легко. –

+1

Argonaut, обеспечивающий легкий кодек для классов case, а также курсор для пользовательской обработки. – cchantep

+0

@cchantep Звучит интересно. Не могли бы вы привести пример? – Michael

ответ

2

Рассмотрите возможность использования Play-JSON, в котором есть объект «Считывает». Если вы когда-либо использовали ReactiveMongo, его можно использовать практически так же. В отличие от некоторых старых сообщений здесь он может использоваться автономно, без большинства остальных Play.

В нем используется общий термин «неявный переводчик» (мой термин). Я обнаружил, что мой любимый десериализационный шаблон для его использования не выделяется в документах, хотя - шаблон, который они поддерживают, намного сложнее получить, ИМХО. Я сильно использую .as и .asOpt, которые описаны на первой связанной странице выше, в небольшом разделе «Использование JsValue.as/asOpt». При десериализации объекта JSON, вы можете сказать что-то вроде

val person:Person = (someParsedJsonObject \ "aPerson").as[Person] 

и до тех пор, пока у вас есть неявное Считывает [Человек] в области видимости, все просто работает. Существуют встроенные читы для всех примитивных типов и многих типов коллекций. Во многих случаях имеет смысл помещать неявные объекты Reads and Writes в объект-компаньон для, например, Person.

Я думал, что у json4s была подобная функция, но я мог ошибаться.

+0

Вы правы, json4s имеет очень схожую функциональность, но я думаю, что он может сериализовать/десериализовать большинство классов случаев без предоставления пользователю каких-либо имплицитов.Не уверен, что это лучше, чем Play-JSON. –

+0

@ RichHenry - Play-JSON может делать классы классов без имплицитов тоже - но для меня, по крайней мере, всегда есть какая-то небольшая дополнительная вещь, которая мне нужна, что делает автоматическое отображение бесполезным - поэтому я не упоминал об этом. Это не из-за какого-либо недостатка автоматического сопоставления, кроме того, что он не может читать мой разум. –

1

Аргонавт полностью функциональный библиотека Scala.

Он позволяет использовать encode/decode case classes (кодеки JSON).

import argonaut._, Argonaut._ 

case class Person(name: String, age: Int) 

implicit def PersonDecodeJson: DecodeJson[Person] 
    jdecode2L(Person.apply)("name", "age") 
    // Codec for Person case class from JSON of form 
    // { "name": "string", "age": 1 } 

Он также предоставляет курсор JSON (линзы/монокл) для индивидуального анализа.

implicit def PersonDecodeJson: DecodeJson[Person] = 
    DecodeJson(c => for { 
    name <- (c --\ "_name").as[String] 
    age <- (c --\ "_age").as[String].map(_.toInt) 
    } yield Person(name, age)) 
    // Decode Person from a JSON with property names different 
    // from those of the case class, and age passed as string: 
    // { "_name": "string", "age": "10" } 

Синтаксический результат представлен DecodeResult типа, которые могут быть в составе (.map, .flatMap) и обрабатывать случаи ошибок.

+0

Спасибо. «Аргонавт» выглядит многообещающим, но мне не нравится их синтаксис DSL (например, '- \'). Я хотел бы также составлять функции парсера (декодирования), а не результаты. Может быть, «линзы» - это абстракция, которую я ищу .. – Michael

+0

Аргонавт как-то много возможностей. Я бы предложил посмотреть на скаладок. – cchantep

Смежные вопросы