Play 2.2 라이브러리로 밀봉된 특성을 위한 노이즈 프리 JSON 형식
간단한 JSON 시리얼라이제이션 솔루션을 최소한의 세레머니로 입수할 필요가 있습니다.그래서 나는 곧 있을 Play 2.2 라이브러리를 발견해서 매우 기뻤다.이것은, 예를 들면, 플레인 케이스 클래스에서 완벽하게 동작합니다.
import play.api.libs.json._
sealed trait Foo
case class Bar(i: Int) extends Foo
case class Baz(f: Float) extends Foo
implicit val barFmt = Json.format[Bar]
implicit val bazFmt = Json.format[Baz]
그러나 다음 작업이 실패합니다.
implicit val fooFmt = Json.format[Foo] // "No unapply function found"
분실된 것으로 추정되는 추출기를 어떻게 설정합니까?Foo
?
아니면 케이스가 완전히 자동으로 처리되는 다른 스탠드아론 라이브러리를 추천하시겠습니까?컴파일 시 매크로든 실행 시 리플렉션이든 개봉 후 바로 사용할 수 있다면 상관없습니다.
개정 2015-09-22
라이브러리 play-json-extra에는 play-json-variants 전략뿐만 아니라 [play-json-extensions]전략(필요가 없는 한 케이스 클래스의 객체와 혼합된 케이스 객체의 플랫 문자열)도 포함됩니다.또한 macramé 기반 Enum을 위한 직렬화 및 역직렬화 기능도 제공합니다.
이전 답변 이제 play-json-variants라는 라이브러리가 있습니다.이 라이브러리는 다음과 같이 기술할 수 있습니다.
implicit val format: Format[Foo] = Variants.format[Foo]
이에 따라 대응하는 형식이 자동으로 생성되며 $variant 속성(0__s에 상당)을 추가하여 다음 대소문자의 명확화도 처리됩니다.class
속성)
sealed trait Foo
case class Bar(x: Int) extends Foo
case class Baz(s: String) extends Foo
case class Bah(s: String) extends Foo
생성되다
val bahJson = Json.obj("s" -> "hello", "$variant" -> "Bah") // This is a `Bah`
val bazJson = Json.obj("s" -> "bye", "$variant" -> "Baz") // This is a `Baz`
val barJson = Json.obj("x" -> "42", "$variant" -> "Bar") // And this is a `Bar`
다음은 의 수동 구현입니다.Foo
companion 객체:
implicit val barFmt = Json.format[Bar]
implicit val bazFmt = Json.format[Baz]
object Foo {
def unapply(foo: Foo): Option[(String, JsValue)] = {
val (prod: Product, sub) = foo match {
case b: Bar => (b, Json.toJson(b)(barFmt))
case b: Baz => (b, Json.toJson(b)(bazFmt))
}
Some(prod.productPrefix -> sub)
}
def apply(`class`: String, data: JsValue): Foo = {
(`class` match {
case "Bar" => Json.fromJson[Bar](data)(barFmt)
case "Baz" => Json.fromJson[Baz](data)(bazFmt)
}).get
}
}
sealed trait Foo
case class Bar(i: Int ) extends Foo
case class Baz(f: Float) extends Foo
implicit val fooFmt = Json.format[Foo] // ça marche!
검증:
val in: Foo = Bar(33)
val js = Json.toJson(in)
println(Json.prettyPrint(js))
val out = Json.fromJson[Foo](js).getOrElse(sys.error("Oh no!"))
assert(in == out)
또는 직접 포맷 정의:
implicit val fooFmt: Format[Foo] = new Format[Foo] {
def reads(json: JsValue): JsResult[Foo] = json match {
case JsObject(Seq(("class", JsString(name)), ("data", data))) =>
name match {
case "Bar" => Json.fromJson[Bar](data)(barFmt)
case "Baz" => Json.fromJson[Baz](data)(bazFmt)
case _ => JsError(s"Unknown class '$name'")
}
case _ => JsError(s"Unexpected JSON value $json")
}
def writes(foo: Foo): JsValue = {
val (prod: Product, sub) = foo match {
case b: Bar => (b, Json.toJson(b)(barFmt))
case b: Baz => (b, Json.toJson(b)(bazFmt))
}
JsObject(Seq("class" -> JsString(prod.productPrefix), "data" -> sub))
}
}
이 시점에서 이상적으로 저는 자동으로 생성하려고 합니다.apply
그리고.unapply
방법들.리플렉션과 매크로 중 하나를 사용해야 할 것 같습니다.
재생 2.7
sealed traits
에서 지원되고 있다.play-json
.
object Foo{
implicit val format = Json.format[Foo]
}
재생 2.6
play-json에서 유래한 코덱으로 우아하게 할 수 있습니다.
이것만 추가해 주세요.
object Foo{
implicit val jsonFormat: OFormat[Foo] = derived.oformat[Foo]()
}
전체 예제는 여기를 참조하십시오.ScalaFiddle
다이렉트 포맷의 정의에 관한 0__의 이전 답변에 대한 작은 수정 - reads 메서드는 작동하지 않았습니다.또, 보다 관용적으로 하기 위한 리팩터도 여기에 있습니다.
def reads(json: JsValue): JsResult[Foo] = {
def from(name: String, data: JsObject): JsResult[Foo] = name match {
case "Bar" => Json.fromJson[Bar](data)(barFmt)
case "Baz" => Json.fromJson[Baz](data)(bazFmt)
case _ => JsError(s"Unknown class '$name'")
}
for {
name <- (json \ "class").validate[String]
data <- (json \ "data").validate[JsObject]
result <- from(name, data)
} yield result
}
언급URL : https://stackoverflow.com/questions/17021847/noise-free-json-format-for-sealed-traits-with-play-2-2-library
'programing' 카테고리의 다른 글
역직렬화 중 JSON.Net 무시 속성 (0) | 2023.02.26 |
---|---|
Moment.js 와 ReactJS (ES6) (0) | 2023.02.26 |
Python: 간단한 설정/구성 파일을 저장하는 방법은 무엇입니까? (0) | 2023.02.26 |
WordPress에서 현재 사용자의 역할을 아는 방법 (0) | 2023.02.26 |
jQuery ajax 호출에 여러 파라미터 전달 (0) | 2023.02.26 |