在PlayFramework 2.4中使用JSON转换器添加可选属性 [英] Add optional property with json transformers in playframework 2.4

查看:95
本文介绍了在PlayFramework 2.4中使用JSON转换器添加可选属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不明白,如何使用json转换器添加可选属性.

I can't understand, how can i add optional property with json transformer.

我想合并两个json对象(列表和日历),不带或带有动态属性列表(例如,不带owner):

I want merge two json objects (list and calendars) without or with dynamic list of properties (for example without owner):

calendar1 = {id:1, name: "first", description:"my first calendar", owner: 1}
calendar2 = {id:2, name: "second", owner: 1}

list = [{id: 1, settings: []}, {id: 2, settings: []}]

结果必须为

{calendars:
    [
      {id:1, name: "first", description:"my first calendar", settings: []}, 
      {id:2, name: "second", settings: []}
    ]
}

推荐答案

我将假设以下json树

I'll assume the following json trees

val calendar1 = Json.parse("""{"id":1, "name": "first", "description":"my first calendar", "owner": 1}""")
val calendar2 = Json.parse("""{"id":2, "name": "second", "owner": 1}""")

您需要为每个日历添加设置,然后删除所有者(如果存在).

You need to add settings to each calendar, then remove the owner if it exists.

在分支settings中放置值是

删除所有者也是解释

val removeOwner = (__ \ "owner").json.prune

现在您可以定义要应用于每个日历对象的转换器

Now you can define the transformer to be applied to each of your calendar object

val transformer = addSettings andThen removeOwner

有了这些,根据实际数据建模的方式,有多个选项.如果您有

With that in place there are multiple options depending on how your data is actually modeled. If you have a Seq of calendars as in

val calendars = Seq(calendar1, calendar2)

可以做到

val normalizedCalendars = calendars.map(_.transform(transformer)) 

这为您提供了一个Seq[JsResult[JsObject]],您希望将其转换为JsResult[Seq[JsObject]].

This gives you a Seq[JsResult[JsObject]] which you want to transform into a JsResult[Seq[JsObject]].

我很确定有一种方法可以使用play的功能语法(请参阅play.api.libs.functionalplay.api.libs.functional.syntax),但是这部分内容没有得到很好的记录,我还没有研究Applicatives即使我对他们的工作有感觉.

I am pretty sure there is a way to do it using play's functional syntax (see play.api.libs.functional and play.api.libs.functional.syntax) but this part of play is not well documented and I haven't gotten around to studying Applicatives yet even though I have a feel for what they do.

相反,我依赖于受scala Future#sequence

Instead, I rely on the following code inspired by scala's Future#sequence

def sequence[A, M[X] <: TraversableOnce[X]](in: M[JsResult[A]])(implicit cbf: CanBuildFrom[M[JsResult[A]], A, M[A]]): JsResult[M[A]] = {
  val empty: JsResult[mutable.Builder[A, M[A]]] = JsSuccess(cbf(in))
  in.foldLeft(empty) {(jracc,jrel) => (jracc,jrel) match {
      case (JsSuccess(builder,_), JsSuccess(a,p)) =>JsSuccess(builder+=a, p)
      case (ra@JsError(builderErrors), re@JsError(errors)) =>JsError.merge(ra, re)
      case (JsSuccess(_,_), re@JsError(errors)) => re
      case (ra@JsError(builderErrors), JsSuccess(_,_)) => ra
    }} map (_.result())
}

您可以这样写:

val calendarArray = sequence(normalizedCalendars).map(v=>Json.obj("calendars"->JsArray(v)))

,这将为您提供JsResult[JsObject].只要您的原始日历确实是JsObject,您就会得到一个JsSuccess.您可以使用以下命令验证输出结构:

which will give you a JsResult[JsObject]. As long as your original calendars are indeed JsObjects you will get a JsSuccess. You can verify the output structure with :

calendarArray.foreach(println)

返回:

{"calendars":[{"id":1,"name":"first","description":"my first calendar","settings":[]},{"id":2,"name":"second","settings":[]}]}

与您对某些空格取模的要求相同

which is the same as what you asked modulo some whitespace

{
  "calendars":[
    {"id":1,"name":"first","description":"my first calendar","settings":[]},
    {"id":2,"name":"second","settings":[]}
  ]
}

这篇关于在PlayFramework 2.4中使用JSON转换器添加可选属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆