我有两个从案例类创建的JsValue,即Book and 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转换,请告诉我。非常感谢!
答案 0 :(得分:15)
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,您可以选择任一选项。
答案 1 :(得分:2)
JsObject是JsValue的子类型。
可以使用JsValue中的 as 或 asOpt 方法将JsValue简单地转换为JsObject。 例如:
<cfset newSheet = spreadsheetNew('Need Approval')>
<cfset headerRow = spreadsheetAddRow(newSheet,'ContactID,FirstName,LastName,Organization,RegisterDate,Approve,Deny')>
<cfset i = 2>
<cfoutput query="getNotApproved">
<cfset newRow = spreadsheetAddRow(newSheet,'#ContactID#,#FirstName#,#LastName#,#Organization#,#RegisterDate#',#i#,1)>
<cfset addApprove = spreadsheetSetCellFormula(newSheet,"HYPERLINK(https://mysite/approvalStatus.cfm?sts=approved&cid=#ContactID#&udf=#getShowrooms.Showroom#,'Click here to Approve')",#i#,6)>
<cfset addDeny = spreadsheetSetCellFormula(newSheet,"HYPERLINK(https://mysite/approvalStatus.cfm?sts=deny&cid=#ContactID#&udf=#getShowrooms.Showroom#,'Click here to Deny')",#i#,7)>
<cfset i++>
</cfoutput>
在JsArray 的情况下,您无法使用上述代码。 如果您使用play并使用数组解析JSON,那么 Json.toJson(...)会生成JsValue,实际上是JsArray。 您需要转换JsArray如下:
val someJsValue = ....
val asObject:JsObject = someJsValue.as[JsObject]
val asObjectMaybe:Option[JsObject] = v.asOpt[JsObject]