Каков самый простой способ разобрать JSON в Scala?

Из старой статьи Дэна Сакса ( http://www.ddj.com/cpp/184403396?pgno=3 ):


The C языковые правила для именования структур немного эксцентричны, но они довольно безобидны. Однако, когда они распространяются на классы в C ++, те же самые правила открывают маленькие трещины для ошибок, чтобы пролистать.

В C имя s, встречающееся в

struct s
    {
    ...
    };

, является тегом. Имя тега не является именем типа. Учитывая приведенное выше определение, такие объявления, как

s x;    /* error in C */
s *p;   /* error in C */

, являются ошибками в C. Вы должны записать их как

struct s x;     /* OK */
struct s *p;    /* OK */

Имена объединений и перечислений также являются тегами, а не типами.

В Си теги отличаются от всех других имен (для функций, типов, переменных и констант перечисления). Компиляторы C поддерживают теги в таблице символов, которая концептуально, если не физически отделена от таблицы, которая содержит все другие имена. Таким образом, программа на Си может иметь тег и другое имя с одинаковым написанием в одной и той же области видимости. Например,

struct s s;

является допустимым объявлением, которое объявляет переменную s типа struct s. Это не может быть хорошей практикой, но компиляторы C должны принять это. Я никогда не видел обоснования того, почему C был разработан таким образом. Я всегда думал, что это ошибка, но она есть.

Многие программисты (в том числе и ваши) предпочитают воспринимать имена структур как имена типов, поэтому они определяют псевдоним для тега, используя typedef. Например, определение

struct s
    {
    ...
    };
typedef struct s S;

позволяет использовать S вместо struct s, как в

S x;
S *p;

Программа не может использовать S в качестве имени как типа, так и переменной ( или функция или константа перечисления):

S S;    // error

Это хорошо.

Имя тега в определении структуры, объединения или перечисления является необязательным. Многие программисты складывают определение структуры в typedef и вообще обходятся без тега, например:

typedef struct
    {
    ...
    } S;

В связанной статье также обсуждается, как поведение C ++ не требует typedef может вызвать скрытые проблемы со скрытием имен. Чтобы предотвратить эти проблемы, неплохо было бы typedef также использовать классы и структуры в C ++, хотя на первый взгляд это кажется ненужным. В C ++ с typedef скрытие имени становится ошибкой, о которой говорит вам компилятор, а не скрытым источником потенциальных проблем.

18
задан Mario Galic 2 November 2017 в 00:06
поделиться

1 ответ

Вот краткие примеры десериализации необработанной строки JSON в модель класса дел для различных библиотек Scala JSON:

play-json

import play.api.libs.json._

case class User(id: Int, name: String)

object User {
  implicit val codec = Json.format[User]
}

object PlayJson extends App {
  val string = """{"id": 124, "name": "John"}"""
  val json = Json.parse(string)
  val user = json.as[User]
  println(user)
}

lift-json

import net.liftweb.json._

case class User(id: Int, name: String)

object LiftJson extends App {
  implicit val codec = DefaultFormats
  val string = """{"id": 124, "name": "John"}"""
  val json = parse(string)
  val user = json.extract[User]
  println(user)
}

spray-json

import spray.json._
import DefaultJsonProtocol._

case class User(id: Int, name: String)

object UserJsonProtocol extends DefaultJsonProtocol {
  implicit val codec = jsonFormat2(User)
}

object SprayJson extends App {
  import UserJsonProtocol._
  val string = """{"id": 124, "name": "John"}"""
  val json = string.parseJson
  val user = json.convertTo[User]
  println(user)
}

сфера-json

import io.sphere.json.generic._
import io.sphere.json._

case class User(id: Int, name: String)

object SphereJson extends App {
  implicit val codec = deriveJSON[User]
  val string = """{"id": 124, "name": "John"}"""
  val user = fromJSON[User](string)
  println(user)
}

аргонавт

import argonaut._ 
import Argonaut._

case class User(id: Int, name: String)

object ArgonautJson extends App {
  implicit def codec = casecodec2(User.apply, User.unapply)("id", "name")
  val string = """{"id": 124, "name": "John"}"""
  val user = string.decodeOption[User]
  println(user)
}

circe

import io.circe.generic.auto._
import io.circe.parser._

case class User(id: Int, name: String)

object CirceJson extends App {
  val string = """{"id": 124, "name": "John"}"""
  val user = decode[User](string)
  println(user)
}

Вот зависимости для приведенных выше примеров:

resolvers += Resolver.bintrayRepo("commercetools", "maven")

libraryDependencies ++= Seq(

  "com.typesafe.play" %% "play-json"      % "2.6.7",
  "net.liftweb"       %% "lift-json"      % "3.1.1",
  "io.spray"          %% "spray-json"     % "1.3.3",
  "io.sphere"         %% "sphere-json"    % "0.9.0",
  "io.argonaut"       %% "argonaut"       % "6.2",
  "io.circe"          %% "circe-core"     % "0.8.0",
  "io.circe"          %% "circe-generic"  % "0.8.0",
  "io.circe"          %% "circe-parser"   % "0.8.0"
)

Этот пост был вдохновлен следующей статьей: Краткий обзор Библиотеки JSON в Scala

Соответствующий вопрос SO: Какую библиотеку JSON использовать в Scala?

0
ответ дан 30 November 2019 в 07:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: