【问题标题】:No instance of play.api.libs.json.Format is available for scala.Predef.Map[java.lang.String, scala.Option[scala.Double]]scala.Predef.Map[java.lang.String, scala.Option[scala.Double]] 没有 play.api.libs.json.Format 的实例
【发布时间】:2018-04-21 01:24:30
【问题描述】:

尝试为包含选项映射的实体编写 json 格式。它抛出以下错误

错误:(8, 68) 没有 play.api.libs.json.Format 实例可用于隐式范围内的 scala.Predef.Map[java.lang.String, scala.Option[scala.Double]] (提示:如果在同一个文件中声明,请确保之前声明过)

代码sn-p:

import play.api.libs.json.{Json, OFormat}

val a: Map[String, Option[Double]] = Map("a" -> None)

case class Person(x: Map[String, Option[Double]])

object Person {
  implicit val personFormat: OFormat[Person] = Json.format[Person]
}

Json.toJson(Person(a))

【问题讨论】:

    标签: json scala playframework play-json


    【解决方案1】:

    问题似乎是 play-json 宏无法使用嵌套类型变量:

    Map[String, Option[Double]]

    您可以使用中间类型包装选项

    import play.api.libs.json.{Json, OFormat}
    
    case class OptionDouble(value: Option[Double])
    case class Person(x: Map[String, OptionDouble])
    
    implicit val optionDoubleFormat = Json.format[OptionDouble]
    implicit val personFormat = Json.format[Person]
    
    val a: Map[String, OptionDouble] = Map("a" -> OptionDouble(None))
    Json.toJson(Person(a))
    

    另一种选择是手动编写格式化程序。

    【讨论】:

      【解决方案2】:

      你可以定义隐式:

        import scala.collection.Map
      
        object Person {
          implicit object MapReads extends Reads[Map[String, Option[Double]]] {
            def reads(jsValue: JsValue): JsResult[Map[String, Option[Double]]] = jsValue match {
              case JsObject(map) => JsSuccess(
                map.mapValues {
                  case JsNumber(d) => Some(d.toDouble)
                  case _ => None
                }
              )
              case _ => JsError()
            }
          }
      
          implicit object MapWrites extends Writes[Map[String, Option[Double]]] {
            def writes(map: Map[String, Option[Double]]): JsValue =
              JsObject(map.mapValues(optd => JsNumber(optd.getOrElse[Double](0.0))))
          }
      
          implicit val personFormat: OFormat[Person] = Json.format[Person]
        }
      
        println(Json.toJson(Person(a)))//{"x":{"a":0}}
      

      基于answer

      【讨论】:

      • 将 None 值映射到 0.0 可能不是一个好的解决方案,因为它是一个有效值。 None 应该映射到 null。
      • 对隐式写入进行了以下更改,现在它为 None 返回 null。 def writes(map: Map[String, Option[Double]]): JsValue = JsObject(map.mapValues { case None => JsNull case Some(x) => JsNumber(x) })
      • @SujitKamthe 是的,这只是一个如何定义此类隐式的示例。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-12
      • 1970-01-01
      • 1970-01-01
      • 2018-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多