考虑这个案例类
case class Location(val name: String, val id: Option[Long] = None)
我可以写一个" toJson"像这样:
implicit val locationWrites: Writes[Location] = (
(JsPath \ "name").write[String] and
(JsPath \ "id").write[Option[Long]]
) (unlift(Location.unapply))
但是我正在和#34; fromJson":
挣扎implicit val locationReads: Reads[Location] = (
(JsPath \ "name").read[String]
) (Location.apply _, None)
说明:id实际上应该由持久层设置,所以我不想手动提供它。
我也尝试过:
implicit val locationReads: Reads[Location] = (
(JsPath \ "name").read[String] and
(JsPath \ "id").read[Option[Long]]
) (Location.apply _)
但遗憾的是我得到了:
找不到类型为Option [Long]的Json反序列化器。尝试为此类型实现隐式读取或格式。
我真的需要为此创建一个隐含的吗?
为什么这样有效(如:编译)?我问,因为它对人类来说绝对是微不足道的,但突然间有一个隐含的并且它会编译。不知道这是否有意义,但我不担心
implicit val optionalLongReads: Reads[Option[Long]] = (
(JsPath \ "optional").read[Option[Long]]
)
编辑绝对没有意义。
如果我发送curl --include --request POST --header "Content-type:application/json" --data '{"name": "Gondor", "id": "2"}' localhost:9000
,我会:
HTTP / 1.1 500内部服务器错误
内容长度:8029
内容类型:text / html;字符集= UTF-8
日期:星期六,2016年10月8日21:49:51 GMT
我不能把id留空:(
答案 0 :(得分:2)
Play Framework支持开箱即用的Option
字段。
您必须使用readNullable[Long]
代替read[Option[Long]]
。
implicit val locationReads: Reads[Location] = (
(JsPath \ "name").read[String] and
(JsPath \ "id").readNullable[Long]
)(Location.apply _)
您还可以在writeNullable[Long]
中使用locationWrites
。
如果write[Option[Long]]
为id
,则null
结果将id
字段设置为None
。对于writeNullable[Long]
案例,id
None
字段根本不存在:
val location = Location("Gondor", None)
// locationWrites with (JsPath \ "id").write[Option[Long]]
{
"name":"Gondor",
"id":null
}
// locationWrites with (JsPath \ "id").writeNullable[Long]
{
"name":"Gondor"
}
答案 1 :(得分:1)
不确定为什么json lib不直接支持Option
,试试这个:
implicit def readOption[T](implicit inner: Reads[T]): Reads[Option[T]] = inner.map(Some.apply).orElse(Reads.pure(None))
显然他们支持它,试试这个:
(JsPath \ "id").nullable[Long]
yay dsls我猜。
或使用更高级的json库,例如http://argonaut.io/ + https://github.com/alexarchambault/argonaut-shapeless或https://travisbrown.github.io/circe/
答案 2 :(得分:1)
您发送的数据是“id”:“2”,它是字符串。如果你想发送Long,我想尝试“id”:2
答案 3 :(得分:1)
Play json支持为开箱即用的案例类自动生成序列化/反序列化函数,只需使用<global-modules>
<module name="org.postgresql" slot="main"/>
</global-modules>
自动创建所需的Json.format
和Reads
。将它放在案例类的伴随对象中。
Writes
然后使用:
case class Location(val name: String, val id: Option[Long] = None)
object Location {
implicit val locationFormat = Json.format[Location]
}