Json到case类的选项[Long]

时间:2016-10-08 21:46:23

标签: json scala playframework

考虑这个案例类

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留空:(

4 个答案:

答案 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-shapelesshttps://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.formatReads。将它放在案例类的伴随对象中。

Writes

然后使用:

case class Location(val name: String, val id: Option[Long] = None)

object Location {
  implicit val locationFormat = Json.format[Location]
}