簡體   English   中英

如何在平面級別將JsValue合並到JsObject

[英]How to merge a JsValue to JsObject in flat level

我有兩個從case類創建的JsValue,即Book和Book detail

val bookJson = Json.tojson(Book)
val bookDetailJson = Json.tojson(BookDetail)

格式為:

//Book
{
  id: 1,
  name: "A Brief History of Time"
}

//BookDetail
{
  bookId: 1,
  author: "Steven Hawking",
  publicationDate: 1988,
  pages: 256
}

如何將它們合並到play-framework 2.10中的單個Json?

//Book with detail
{
  id: 1,
  name: "A Brief History of Time",
  bookId: 1,
  author: "Steven Hawking",
  publicationDate: 1988,
  pages: 256
}

我正在嘗試轉換,但未能遍歷第二個JsValue:

val mapDetail = (__).json.update(
                  __.read[JsObject].map { o =>
                  o.deepMerge( JsObject(Seq(("detail", bookDetailJson))) )
                })

bookJson.validate(mapDetail).get

它會降低一級,我真的不想要。

//Book with detail
{
  id: 1,
  name: "A Brief History of Time",
  detail: {
            bookId: 1,
            author: "Steven Hawking",
            publicationDate: 1988,
            pages: 256
          }
}

請讓我知道這個Json轉換是否可以提供任何技巧。 非常感謝!

Play現在具有JSON的許多新功能。 這將很好地展示Format[A]特性(請參見Scala Json Inception ),您可以像我將要隱式包括的那樣,或者將其顯式地包含在需要隱式Format[A]/Reads[A]/Writes[A]

創建一個案例類來表示您的JSON對象,

case class Book(id: Int, name: String)
case class BookDetail(id: Int, author: String, publicationDate: Int, pages: Int)

創建包含隱式Format[A]伴隨對象,以便在需要時自動將Format/Reads/Writes包含在范圍內。

object Book { 
  implicit val fmt: Format[Book] = Json.format[Book] 
}

object BookDetail { 
  implicit val fmt: Format[BookDetail] = Json.format[BookDetail] 
}

現在您可以做這樣的事情,

val bookJson = Json.toJson(Book(1, "A Brief History Of Time"))
val bookDetailJson = Json.toJson(BookDetail(1, "Steven Hawking", 1988, 256))
bookJson.as[JsObject].deepMerge(bookDetailJson.as[JsObject])

您將擁有一個這樣的對象,

{
  id: 1,
  name: "A Brief History Of Time",
  author: "Steven Hawking",
  publicationDate: 1988,
  pages: 256
}

我已經在REPL中嘗試過此方法,但是它不起作用,但是在Play應用程序中就可以了。 同樣在生產場景中,我們可能會使用asOpt[T]代替as[T]

這是一個為什么asOpt[T]更適合的示例,假設您所獲得的圖書不是有效的JSON對象,

val bookJson = Json.toJson("not a book")

您最終會得到一個

[JsResultException: JsResultException(errors:List((,List(ValidationError(validate.error.expected.jsobject,WrappedArray())))))]

但是假設您改為將方法更改為使用asOpt[T]

bookJson.asOpt[JsObject].getOrElse(Json.obj()).deepMerge(bookDetailJson.asOpt[JsObject].getOrElse(Json.obj()))

現在,您將最終得到至少一個部分JSON對象,

{
  id: 1,
  author: "Steven Hawking",
  publicationDate: 1988,
  pages: 256
}

因此,根據您要如何處理格式不正確的JSON,可以選擇其中一個選項。

JsObject是JsValue的子類型。

可以使用JsValue中的asasOpt方法將JsValue簡單轉換為JsObject。 例:

val someJsValue = ....
val asObject:JsObject = someJsValue.as[JsObject]
val asObjectMaybe:Option[JsObject] = v.asOpt[JsObject]

對於JsArray,您不能使用上面的代碼。 如果使用play並使用數組解析JSON,則Json.toJson(...)會生成JsValue,它實際上是JsArray。 您需要按以下方式轉換JsArray:

val someJsValueButArray = ....
val asJsArray:JsArray = Json.toJson(someJsValueButArray).as[JsArray]
val asSeqOfJsObjects:Seq[JsObject] = asJsArray.value.map(_.as[JsObject])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM