[英]Play/Scala how to prevent Json serialization of empty arrays?
I want to recursively write a class to Json, so I'm using the following implicit writes: 我想以递归方式将一个类写入Json,因此我使用以下隐式写入:
implicit val writesObject : Writes[Object] = (
(__ \ "id").writeNullable[String] ~
(__ \ "list").lazyWriteNullable(Writes.traversableWrites[Object](writesObject))
)(unlift(Object.unapply)
where Object is a class like this: 其中Object是这样的类:
case class Object(id: Option[String], list: Option[Seq[Object]])
It works, however I would like to prevent it from printing anything if "list" is empty. 它有效,但是如果“list”为空,我想阻止它打印任何东西。 For example:
例如:
I want: 我想要:
{ id: "someID",
list: [
{
id: "someOtherId"
}
]
}
I currently get(but don't want): 我目前得到(但不想要):
{ id: "someID",
list: [
{
id: "someOtherId"
list: []
}
]
}
How can I achieve this? 我怎样才能做到这一点? I'm new to Play/Scala and not sure exactly what should I be looking at so any pointers would be helpful.
我是Play / Scala的新手,不确定我应该注意什么,所以任何指针都会有所帮助。 I'm using Scala 2.2.1.
我正在使用Scala 2.2.1。
PS: I've checked Scala Json Combinators but didn't see any reference on how to get this done. PS:我已经检查过Scala Json Combinators,但没有看到任何关于如何完成这项工作的参考。
Update: 更新:
So my issue is not that list is null, but that list is empty. 所以我的问题不是该列表为空,但该列表为空。 That's why lazyWriteNullable wasn't working.
这就是为什么lazyWriteNullable不起作用的原因。
Testing johanandren answer I came up with the following extension to JsPath that returns Option[T] and supports the lazy format for recursive writes: 测试johanandren的答案我想出了JsPath的以下扩展,返回Option [T]并支持递归写入的惰性格式:
def lazyWriteNullableIterable[T <: Iterable[_]](w: => Writes[T]): OWrites[Option[T]] = OWrites((t: Option[T]) => {
if(t != null) {
t.getOrElse(Seq.empty).size match {
case 0 => Json.obj()
case _ => Writes.nullable[T](path)(w).writes(t)
}
}
else {
Json.obj()
}
})
Thanks 谢谢
You can create a custom OFormat that will do this. 您可以创建一个自定义OFormat来执行此操作。 By implicitly decorating JsPath with it you can include it in your json combinator definitions:
通过使用它隐式装饰JsPath,您可以将它包含在json组合器定义中:
implicit class PathAdditions(path: JsPath) {
def readNullableIterable[A <: Iterable[_]](implicit reads: Reads[A]): Reads[A] =
Reads((json: JsValue) => path.applyTillLast(json).fold(
error => error,
result => result.fold(
invalid = (_) => reads.reads(JsArray()),
valid = {
case JsNull => reads.reads(JsArray())
case js => reads.reads(js).repath(path)
})
))
def writeNullableIterable[A <: Iterable[_]](implicit writes: Writes[A]): OWrites[A] =
OWrites[A]{ (a: A) =>
if (a.isEmpty) Json.obj()
else JsPath.createObj(path -> writes.writes(a))
}
/** When writing it ignores the property when the collection is empty,
* when reading undefined and empty jsarray becomes an empty collection */
def formatNullableIterable[A <: Iterable[_]](implicit format: Format[A]): OFormat[A] =
OFormat[A](r = readNullableIterable(format), w = writeNullableIterable(format))
}
This would allow you to create formats/reads/writes using the json combinator syntax like this: 这将允许您使用json组合器语法创建格式/读/写,如下所示:
case class Something(as: List[String], v: String)
import somewhere.PathAdditions
val reads: Reads[Something] = (
(__ \ "possiblyMissing").readNullableIterable[List[String]] and
(__ \ "somethingElse").read[String]
)(Something)
val writes: Writes[Something] = (
(__ \ "possiblyMissing").writeNullableIterable[List[String]] and
(__ \ "somethingElse").write[String]
)(unlift(Something.unapply))
val format: Format[Something] = (
(__ \ "possiblyMissing").formatNullableIterable[List[String]] and
(__ \ "somethingElse").format[String]
)(Something, unlift(Something.unapply))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.