使用Play的JSON API(play.api.libs.json
)来考虑此示例:
case class FooJson(
// lots of other fields omitted
location: Option[LocationJson]
)
object FooJson {
implicit val writes = Json.writes[FooJson]
}
和
case class LocationJson(latitude: Double, longitude: Double)
object LocationJson {
implicit val writes = Json.writes[LocationJson]
}
如果location
为None
,则生成的JSON根本不会有location
字段。这很好,而且不够深入。但是,如果我出于某种原因(例如,为了让我的API更加自我记录),如何在JSON中明确输出null
?
{
"location": null
}
我还尝试将字段定义为location: LocationJson
并将option.orNull
传递给它,但它不起作用(scala.MatchError: null
位于play.api.libs.json.OWrites$$anon$2.writes
)。对于非自定义类型(如String或Double),此方法将在JSON输出中生成null。
所以,使用Json.writes[FooJson]
,如上所示(或者同样简单的东西,即不必须编写自定义Writes
实现),是否有一种在JSON中包含空值的简洁方法?
我所问的与杰克逊图书馆中的JsonInclude.Include.ALWAYS
类似(也是杰克逊的默认行为)。同样in Gson这将是微不足道的
(new GsonBuilder().serializeNulls().create()
)。
播放2.4.4
答案 0 :(得分:4)
Greg Methvin,一位Play提交者,wrote this answer给我一个相关的GitHub问题:
JSON宏只支持一种编码可选值的方法, 这是从JSON中省略None值。这不是一个bug但是 而是对实施的限制。如果你想包括 遗憾的是,您不得不实施自己的
Writes
。我认为我们应该尝试为此提供更多可配置性 宏虽然。
在这种情况下,我会让Play在值为null时排除此字段,即使它稍微牺牲了API一致性和自我可记录性。它仍然是一个小问题(在这个特定的API中),它不保证代码的泛滥,就像自定义Writes
对具有十几个值的案例类所需要的那样。
我希望他们在未来的Play版本中确实可以配置它。
答案 1 :(得分:0)
这是一种方法:
object MyWrites extends DefaultWrites{
override def OptionWrites[T](implicit fmt: Writes[T]): Writes[Option[T]] = new Writes[Option[T]] {
override def writes(o: Option[T]): JsValue = {
o match {
case Some(a) => Json.toJson(a)(fmt)
case None => JsNull
}
}
}
}
这将覆盖不会创建元素的默认实现。我在你的示例代码中使用了这个:
case class FooJson(
// ...
location: Option[LocationJson]
)
case class LocationJson(latitude: Double, longitude: Double)
object LocationJson {
implicit val writes = Json.writes[LocationJson]
}
implicit val fooJsonWriter: Writes[FooJson] = new Writes[FooJson] {
override def writes(o: FooJson): JsValue = {
JsObject(Seq(
"location" -> Json.toJson(o.location)
// Additional fields go here.
))
}
}
Json.toJson(FooJson(None))
得到了这个结果res0: play.api.libs.json.JsValue = {"location":null}
。
答案 2 :(得分:0)
如果我们具有空值,则必须在case类中添加带有成员的选项,以解决问题
case class response(
name:String,
age: option[int]
)
object response {
implicit val format = Json.format[response]
}
这是我们的答案。并且如果我们是年龄的JSON响应将为null,这将为我们解决问题。
答案 3 :(得分:0)
你好,将来。
从Play 2.7开始,针对自动JSON编解码器引入了一个相当简单的解决方案。我们可以在select t1.*, t2.cost
from table1 t1
inner join table2 t2
on t2.duration between cast(substring(duration, 1, instr(duration, '-') - 1) as int)
and cast(substring(duration, instr(duration, '-') + 1) as int)
/ JsonConfiguration
/ Format
的范围内为Reads
引入适当的隐式值。以下配置将为空的Writes
写入null
,而不是完全忽略这些字段。
Option