Из старой статьи Дэна Сакса ( 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
скрытие имени становится ошибкой, о которой говорит вам компилятор, а не скрытым источником потенциальных проблем.
Вот краткие примеры десериализации необработанной строки JSON в модель класса дел для различных библиотек Scala 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)
}
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)
}
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)
}
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)
}
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?