[SCALA] 플레이 2 JSON 형식으로 누락 된 속성에 대한 기본값
SCALA플레이 2 JSON 형식으로 누락 된 속성에 대한 기본값
나는 플레이 스칼라에서 다음과 같은 모델의 동등한 있습니다
case class Foo(id:Int,value:String)
object Foo{
import play.api.libs.json.Json
implicit val fooFormats = Json.format[Foo]
}
다음 푸 예를 들어
Foo(1, "foo")
나는 다음과 같은 JSON 문서를 얻을 것입니다 :
{"id":1, "value": "foo"}
이 JSON을 지속하고 데이터 저장소에서 읽습니다. 이제 내 요구 사항이 변경되었습니다 난 푸에 속성을 추가해야합니다. 속성은 기본값이 :
case class Foo(id:String,value:String, status:String="pending")
JSON에 쓰는 것은 문제가되지 않습니다 :
{"id":1, "value": "foo", "status":"pending"}
그것에서 읽기 그러나 "/ 상태"경로 누락에 대한 JsError을 산출한다.
어떻게 최소한의 소음과 기본을 제공 할 수 있습니까?
(PS : 나는 아래에 게시 할 예정입니다 대답을하지만 난 정말 그것으로 만족하지 오전 upvote에와 더 나은 옵션을 받아들이)
해결법
-
==============================
1.2.6 재생
2.6 재생
CanardMoussant의 대답 @ 따라, 재생 2.6로 시작하는 플레이 JSON 매크로 개선 및 역 직렬화 할 때 자리로 기본값을 사용하는 등의 여러 새로운 기능을 제안하고있다 :
implicit def jsonFormat = Json.using[Json.WithDefaultValues].format[Foo]
아래 옵션 중 하나를 사용하여 2.6 최선의 선택이 남아 아래 플레이의 경우 :
플레이 JSON-추가
나는이 문제의 하나를 포함하여 플레이 JSON로했다 단점의 대부분을 훨씬 더 나은 솔루션에 대해 알게 :
플레이 JSON-별도의 사용 [플레이 JSON-확장] 내부적으로이 문제의 특정 문제를 해결하기 위해.
자동으로 발생하기 쉬운 오류 훨씬 덜 refactors을 만드는 시리얼 라이저 / 디시리얼라이저에서 누락 된 기본값을 포함하는 매크로를 포함!
import play.json.extra.Jsonx implicit def jsonFormat = Jsonx.formatCaseClass[Foo]
플레이 JSON-추가 : 검사 할 수있는 라이브러리에 더가있다
JSON 변압기
나의 현재 솔루션은 JSON 변압기를 만들고이 매크로에 의해 생성 읽습니다와 결합하는 것입니다. 변압기는 이하의 방법에 의해 생성된다 :
object JsonExtensions{ def withDefault[A](key:String, default:A)(implicit writes:Writes[A]) = __.json.update((__ \ key).json.copyFrom((__ \ key).json.pick orElse Reads.pure(Json.toJson(default)))) }
형식 정의는 다음이된다 :
implicit val fooformats: Format[Foo] = new Format[Foo]{ import JsonExtensions._ val base = Json.format[Foo] def reads(json: JsValue): JsResult[Foo] = base.compose(withDefault("status","bidon")).reads(json) def writes(o: Foo): JsValue = base.writes(o) }
과
Json.parse("""{"id":"1", "value":"foo"}""").validate[Foo]
기본 값을 적용하여 실제로 푸의 인스턴스를 생성합니다.
이것은 내 의견이 주요 결함이있다 :
-
==============================
2.내가 찾은 것을 가장 깨끗한 방법은, 예를 들어, 사용 "순수"이다
내가 찾은 것을 가장 깨끗한 방법은, 예를 들어, 사용 "순수"이다
... ((JsPath \ "notes").read[String] or Reads.pure("")) and ((JsPath \ "title").read[String] or Reads.pure("")) and ...
기본이 일정 할 때이 정상적인 암시 적 방법으로 사용할 수 있습니다. 그것의 동적, 다음 방법을 작성해야하는 경우가 읽어 들여 만든 다음 범위 인, 라를 소개합니다
implicit val packageReader = makeJsonReads(jobId, url)
-
==============================
3.대안적인 해결책은 InvariantFunctor에서 inmap 결합 formatNullable [T]를 사용하는 것이다.
대안적인 해결책은 InvariantFunctor에서 inmap 결합 formatNullable [T]를 사용하는 것이다.
import play.api.libs.functional.syntax._ import play.api.libs.json._ implicit val fooFormats = ((__ \ "id").format[Int] ~ (__ \ "value").format[String] ~ (__ \ "status").formatNullable[String].inmap[String](_.getOrElse("pending"), Some(_)) )(Foo.apply, unlift(Foo.unapply))
-
==============================
4.나는 공식적인 답변 지금 플레이 JSON 2.6 함께 오는 WithDefaultValues를 사용하도록해야한다고 생각 :
나는 공식적인 답변 지금 플레이 JSON 2.6 함께 오는 WithDefaultValues를 사용하도록해야한다고 생각 :
implicit def jsonFormat = Json.using[Json.WithDefaultValues].format[Foo]
편집하다:
주의하는 것이 중요하다 플레이 JSON-추가 라이브러리에서 행동 다릅니다. 예를 들어 당신이 DateTime.Now에 대한 기본 값을 갖는 날짜 시간 매개 변수가있는 경우에, 당신은 이제 프로세스의 시작 시간을 얻을 것이다 - 아마 당신이 원하지 않는 무엇을 - 당신은 창조의 시간을 가졌다 플레이 JSON-추가와 반면 JSON에서.
-
==============================
5.난 그냥 (사용자 측 즉 옵션) 나는 모든 JSON 필드는 선택 사양하고 싶은 경우에 직면했지만 내부적으로 나는 모든 필드는 사용자가 특정 필드를 지정하지 않는 경우 정확하게 정의 된 기본값이 아닌 선택 사항으로합니다. 이 사용 사례와 유사합니다.
난 그냥 (사용자 측 즉 옵션) 나는 모든 JSON 필드는 선택 사양하고 싶은 경우에 직면했지만 내부적으로 나는 모든 필드는 사용자가 특정 필드를 지정하지 않는 경우 정확하게 정의 된 기본값이 아닌 선택 사항으로합니다. 이 사용 사례와 유사합니다.
나는 현재 단순히 완전히 선택적 인수와 푸의 건설을 랩하는 방법을 고려 중이 야 :
case class Foo(id: Int, value: String, status: String) object FooBuilder { def apply(id: Option[Int], value: Option[String], status: Option[String]) = Foo( id getOrElse 0, value getOrElse "nothing", status getOrElse "pending" ) val fooReader: Reads[Foo] = ( (__ \ "id").readNullable[Int] and (__ \ "value").readNullable[String] and (__ \ "status").readNullable[String] )(FooBuilder.apply _) } implicit val fooReader = FooBuilder.fooReader val foo = Json.parse("""{"id": 1, "value": "foo"}""") .validate[Foo] .get // returns Foo(1, "foo", "pending")
불행하게도, 당신이 피하기 위해 원하는 것을 아마 인, 명시 적 [푸] 읽기 및 쓰기 [푸] 작성이 필요합니다? 하나 더 단점은 키가 없거나 값이 null의 경우 기본값 만 사용하는 것입니다. 키가 잘못된 유형의 값을 포함하지만 경우, 다시 전체 검증은 ValidationError를 반환합니다.
이러한 옵션 JSON 구조를 중첩하는 것은 인스턴스에 대한 문제가되지 않습니다 :
case class Bar(id1: Int, id2: Int) object BarBuilder { def apply(id1: Option[Int], id2: Option[Int]) = Bar( id1 getOrElse 0, id2 getOrElse 0 ) val reader: Reads[Bar] = ( (__ \ "id1").readNullable[Int] and (__ \ "id2").readNullable[Int] )(BarBuilder.apply _) val writer: Writes[Bar] = ( (__ \ "id1").write[Int] and (__ \ "id2").write[Int] )(unlift(Bar.unapply)) } case class Foo(id: Int, value: String, status: String, bar: Bar) object FooBuilder { implicit val barReader = BarBuilder.reader implicit val barWriter = BarBuilder.writer def apply(id: Option[Int], value: Option[String], status: Option[String], bar: Option[Bar]) = Foo( id getOrElse 0, value getOrElse "nothing", status getOrElse "pending", bar getOrElse BarBuilder.apply(None, None) ) val reader: Reads[Foo] = ( (__ \ "id").readNullable[Int] and (__ \ "value").readNullable[String] and (__ \ "status").readNullable[String] and (__ \ "bar").readNullable[Bar] )(FooBuilder.apply _) val writer: Writes[Foo] = ( (__ \ "id").write[Int] and (__ \ "value").write[String] and (__ \ "status").write[String] and (__ \ "bar").write[Bar] )(unlift(Foo.unapply)) }
-
==============================
6.이것은 아마도 "최소한의 소음"요구 사항을 만족하지 않습니다,하지만 이유는 옵션 [문자열]로 새 매개 변수를 도입하지?
이것은 아마도 "최소한의 소음"요구 사항을 만족하지 않습니다,하지만 이유는 옵션 [문자열]로 새 매개 변수를 도입하지?
case class Foo(id:String,value:String, status:Option[String] = Some("pending"))
오래된 클라이언트에서 푸를 읽을 때, 당신은 당신의 소비자 코드 (A getOrElse에) 그때 처리 할 거라고 없음을 얻을 수 있습니다.
당신이 마음에 들지 않으면 또는, BackwardsCompatibleFoo를 소개합니다 :
case class BackwardsCompatibleFoo(id:String,value:String, status:Option[String] = "pending") case class Foo(id:String,value:String, status: String = "pending")
다음 코드에 따라 데이터 체조 모두 이런 종류의 처리해야 할 피, 더에 작업 할 푸에 하나를 켜십시오.
-
==============================
7.당신은 옵션으로 상태를 정의 할 수 있습니다
당신은 옵션으로 상태를 정의 할 수 있습니다
case class Foo(id:String, value:String, status: Option[String])
사용 JsPath 너무 좋아 :
(JsPath \ "gender").readNullable[String]
from https://stackoverflow.com/questions/20616677/defaults-for-missing-properties-in-play-2-json-formats by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 스칼라 / 스파크 : 마지막 관찰과 앞으로 채우기 (0) | 2019.11.06 |
---|---|
[SCALA] 스칼라에서 선형화 순서 (0) | 2019.11.06 |
[SCALA] 스칼라 지원 꼬리 재귀 최적화합니까? (0) | 2019.11.06 |
[SCALA] 케이스 클래스는 하나 개의 필드가있는 경우 경우 클래스에 JSON을 설정하는 방법 (0) | 2019.11.06 |
[SCALA] 스칼라의 '::'연산자, 어떻게 작동합니까? (0) | 2019.11.06 |