수색…


JSON with spray-json

spray-json 은 JSON을 사용하기 쉬운 방법을 제공합니다. 암시 적 형식을 사용하면 모든 것이 "배후에서"발생합니다.

SBT로 라이브러리를 사용 가능하게 만들기

SBT 관리 라이브러리 종속성 을 사용하여 spray-json 을 관리하려면 다음을 수행하십시오.

libraryDependencies += "io.spray" %% "spray-json" % "1.3.2"

마지막 매개 변수 인 버전 번호 ( 1.3.2 )는 프로젝트마다 다를 수 있습니다.

spray-json 라이브러리는 repo.spray.io 에서 호스팅됩니다.

라이브러리 가져 오기

import spray.json._
import DefaultJsonProtocol._

기본 JSON 프로토콜 DefaultJsonProtocol 에는 모든 기본 유형의 형식이 포함되어 있습니다. 사용자 정의 유형에 JSON 기능을 제공하려면 형식에 대해 편리한 빌더를 사용하거나 형식을 명시 적으로 작성하십시오.

JSON 읽기

// generates an intermediate JSON representation (abstract syntax tree)
val res = """{ "foo": "bar" }""".parseJson // JsValue = {"foo":"bar"}

res.convertTo[Map[String, String]] // Map(foo -> bar)

JSON 작성

val values = List("a", "b", "c")
values.toJson.prettyPrint // ["a", "b", "c"]

DSL

DSL은 지원되지 않습니다.

사례 클래스에 대한 읽기 - 쓰기

다음 예제는 대소 문자 클래스 객체를 JSON 형식으로 직렬화하는 방법을 보여줍니다.

case class Address(street: String, city: String)
case class Person(name: String, address: Address)

// create the formats and provide them implicitly
implicit val addressFormat = jsonFormat2(Address)
implicit val personFormat = jsonFormat2(Person)

// serialize a Person
Person("Fred", Address("Awesome Street 9", "SuperCity"))
val fredJsonString = fred.toJson.prettyPrint

결과적으로 다음 JSON이 발생합니다.

{
  "name": "Fred",
  "address": {
    "street": "Awesome Street 9",
    "city": "SuperCity"
  }
}

JSON은 객체로 deserialize 될 수 있습니다.

val personRead = fredJsonString.parseJson.convertTo[Person] 
//Person(Fred,Address(Awesome Street 9,SuperCity))

사용자 정의 형식

유형의 특수 직렬화가 필요한 경우 사용자 정의 JsonFormat 작성하십시오. 예를 들어 스칼라에서 필드 이름이 JSON과 다른 경우 또는 입력에 따라 다른 구체 유형이 인스턴스화되는 경우

implicit object BetterPersonFormat extends JsonFormat[Person] {
    // deserialization code
    override def read(json: JsValue): Person = {
        val fields = json.asJsObject("Person object expected").fields
        Person(
            name = fields("name").convertTo[String],
            address = fields("home").convertTo[Address]
        )
    }

    // serialization code
    override def write(person: Person): JsValue = JsObject(
        "name" -> person.name.toJson,
        "home" -> person.address.toJson
    )
}

Circe가있는 JSON

Circe 는 en / decode json 용 컴파일 타임 파생 코덱을 사례 클래스에 제공합니다. 간단한 예제는 다음과 같습니다.

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

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

val user = User(1, "John Doe")

// {"id":1,"name":"John Doe"}
val json = user.asJson.noSpaces

// Right(User(1L, "John Doe"))
val res: Either[Error, User] = decode[User](json)

JSON with play-json

play-json은 암묵적인 형식을 다른 json 프레임 워크로 사용합니다.

SBT 종속성 : libraryDependencies += ""com.typesafe.play" %% "play-json" % "2.4.8"

import play.api.libs.json._
import play.api.libs.functional.syntax._ // if you need DSL

DefaultFormat 는 모든 기본 유형을 읽고 쓸 수있는 기본 형식을 포함합니다. 자신의 유형에 JSON 기능을 제공하려면 형식에 대해 편리한 빌더를 사용하거나 형식을 명시 적으로 작성할 수 있습니다.

json 읽기

// generates an intermediate JSON representation (abstract syntax tree)
val res = Json.parse("""{ "foo": "bar" }""") // JsValue = {"foo":"bar"}

res.as[Map[String, String]]                  // Map(foo -> bar)
res.validate[Map[String, String]]            //JsSuccess(Map(foo -> bar),)

json 작성

val values = List("a", "b", "c")
Json.stringify(Json.toJson(values))          // ["a", "b", "c"]

DSL

val json = parse("""{ "foo": [{"foo": "bar"}]}""")
(json \ "foo").get                    //Simple path: [{"foo":"bar"}]
(json \\ "foo")                       //Recursive path:List([{"foo":"bar"}], "bar")
(json \ "foo")(0).get                  //Index lookup (for JsArrays): {"foo":"bar"}

JsSuccess / JsError 에 대한 패턴 매칭을 항상 선호하며 .get , array(i) 호출을 피하려고합니다.

사례 클래스 읽기 및 쓰기

case class Address(street: String, city: String)
case class Person(name: String, address: Address)

// create the formats and provide them implicitly
implicit val addressFormat = Json.format[Address]
implicit val personFormat = Json.format[Person]

// serialize a Person
val fred = Person("Fred", Address("Awesome Street 9", "SuperCity"))
val fredJsonString = Json.stringify(Json.toJson(Json.toJson(fred)))

val personRead = Json.parse(fredJsonString).as[Person] //Person(Fred,Address(Awesome Street 9,SuperCity))

자신의 형식

유형의 특수한 직렬화가 필요한 경우 (예 : scala와 Json에서 필드의 이름을 다르게하거나 입력을 기반으로 다른 구체적인 유형을 인스턴스화하는 경우) 사용자 고유의 JsonFormat을 작성할 수 있습니다.

case class Address(street: String, city: String)

// create the formats and provide them implicitly
implicit object AddressFormatCustom extends Format[Address] {
  def reads(json: JsValue): JsResult[Address] = for {
    street <- (json \ "Street").validate[String]
    city <- (json \ "City").validate[String]
  } yield Address(street, city)

  def writes(x: Address): JsValue = Json.obj(
    "Street" -> x.street,
    "City" -> x.city
  )
}
// serialize an address
val address = Address("Awesome Street 9", "SuperCity")
val addressJsonString = Json.stringify(Json.toJson(Json.toJson(address)))
//{"Street":"Awesome Street 9","City":"SuperCity"}

val addressRead = Json.parse(addressJsonString).as[Address] 
//Address(Awesome Street 9,SuperCity)

대안

json이 대소 문자 클래스 필드와 정확히 일치하지 않는 경우 (json의 클래스 대 is_alive isAlive ) :

case class User(username: String, friends: Int, enemies: Int, isAlive: Boolean)

object User {

  import play.api.libs.functional.syntax._
  import play.api.libs.json._

  implicit val userReads: Reads[User] = (
      (JsPath \ "username").read[String] and
      (JsPath \ "friends").read[Int] and
      (JsPath \ "enemies").read[Int] and
      (JsPath \ "is_alive").read[Boolean]
    ) (User.apply _)
}

선택적 필드가있는 Json

case class User(username: String, friends: Int, enemies: Int, isAlive: Option[Boolean])

object User {

  import play.api.libs.functional.syntax._
  import play.api.libs.json._

  implicit val userReads: Reads[User] = (
      (JsPath \ "username").read[String] and
      (JsPath \ "friends").read[Int] and
      (JsPath \ "enemies").read[Int] and
      (JsPath \ "is_alive").readNullable[Boolean]
    ) (User.apply _)
}

json에서 타임 스탬프 읽기

유닉스 타임 스탬프 필드가있는 Json 객체가 있다고 가정 해보십시오.

{
  "field": "example field",
  "date": 1459014762000
}

해결책:

case class JsonExampleV1(field: String, date: DateTime)
object JsonExampleV1{
  implicit val r: Reads[JsonExampleV1] = (
    (__ \ "field").read[String] and
      (__ \ "date").read[DateTime](Reads.DefaultJodaDateReads)
    )(JsonExampleV1.apply _)
}

커스텀 케이스 클래스 읽기

이제 형식 안전성을 위해 개체 식별자를 래핑하면이를 즐길 수 있습니다. 다음 json 객체를 참조하십시오.

{
  "id": 91,
  "data": "Some data"
}

및 해당 사례 클래스 :

case class MyIdentifier(id: Long)

case class JsonExampleV2(id: MyIdentifier, data: String)

이제 기본 유형 (Long)을 읽고 idenfier에 매핑해야합니다.

object JsonExampleV2 {
  implicit val r: Reads[JsonExampleV2] = (
      (__ \ "id").read[Long].map(MyIdentifier) and
    (__ \ "data").read[String]
    )(JsonExampleV2.apply _)
}

https://github.com/pedrorijo91/scala-play-json-examples 에서 코드

JSON과 json4s

json4s는 암시 적 형식을 다른 json 프레임 워크로 사용합니다.

SBT 의존성 :

libraryDependencies += "org.json4s" %% "json4s-native" % "3.4.0"
//or
libraryDependencies += "org.json4s" %% "json4s-jackson" % "3.4.0"

수입품

import org.json4s.JsonDSL._
import org.json4s._
import org.json4s.native.JsonMethods._

implicit val formats = DefaultFormats

DefaultFormats 는 모든 기본 유형을 읽고 쓸 수있는 기본 형식을 포함합니다.

json 읽기

// generates an intermediate JSON representation (abstract syntax tree)
val res = parse("""{ "foo": "bar" }""")           // JValue = {"foo":"bar"}
res.extract[Map[String, String]]                  // Map(foo -> bar)

json 작성

val values = List("a", "b", "c")
compact(render(values))         // ["a", "b", "c"]

DSL

json \ "foo"       //Simple path: JArray(List(JObject(List((foo,JString(bar))))))
json \\ "foo"      //Recursive path: ~List([{"foo":"bar"}], "bar")
(json \ "foo")(0)  //Index lookup (for JsArrays): JObject(List((foo,JString(bar))))
("foo" -> "bar") ~ ("field" -> "value")    // {"foo":"bar","field":"value"}

사례 클래스 읽기 및 쓰기

import org.json4s.native.Serialization.{read, write}

case class Address(street: String, city: String)
val addressString = write(Address("Awesome stree", "Super city")) 
// {"street":"Awesome stree","city":"Super city"}

read[Address](addressString) // Address(Awesome stree,Super city)
//or
parse(addressString).extract[Address]

이질적 목록 읽기 및 쓰기

이종 (또는 다형) 목록을 serialize하고 deserialize하려면 특정 형식 힌트를 제공해야합니다.

trait Location
case class Street(name: String) extends Location
case class City(name: String, zipcode: String) extends Location
case class Address(street: Street, city: City) extends Location
case class Locations (locations : List[Location])

implicit val formats = Serialization.formats(ShortTypeHints(List(classOf[Street], classOf[City], classOf[Address])))

val locationsString = write(Locations(Street("Lavelle Street"):: City("Super city","74658")))

read[Locations](locationsString)

자신의 형식

class AddressSerializer extends CustomSerializer[Address](format => (
  {
    case JObject(JField("Street", JString(s)) :: JField("City", JString(c)) :: Nil) =>
      new Address(s, c)
  },
  {
    case x: Address => ("Street" -> x.street) ~ ("City" -> x.city)
  }
  ))

implicit val formats = DefaultFormats + new AddressSerializer
val str = write[Address](Address("Awesome Stree", "Super City"))
// {"Street":"Awesome Stree","City":"Super City"}
read[Address](str) 
// Address(Awesome Stree,Super City)


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow