2017-11-08 5 views
1

含まれるエンティティのjson形式を書き込もうとしていますオプションの地図playa.Predef.Map [skel.Option [scala.Double]]に対してplay.api.libs.json.Formatのインスタンスは使用できません

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)) 

答えて

2

あなたは暗黙に定義することができます。

answerに基づいて
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}} 

+0

Noneに値を0.0にマッピングすることは、有効な値であるため、良い解決策ではない場合があります。 Noneはnullにマップする必要があります。 –

+0

次の暗黙的な書き込みに対する変更を加え、現在はNoneにnullを返します。 JsObject(map.mapValues { ケースなし=> JsNull ケース(x)=> JsNumber(x) ) ' –

+0

@ SuhitKamtheはい、これはそのような暗黙の定義方法の一例にすぎません。 –

0
問題は、ネストされた型変数で動作するようにプレイJSONマクロのできないことであるように思わ

Map[String, Option[Double]]

あなたはエラー

Error:(8, 68) No instance of play.api.libs.json.Format is available for scala.Predef.Map[java.lang.String, scala.Option[scala.Double]] in the implicit scope (Hint: if declared in the same file, make sure it's declared before)

コードスニペット以下のスロー中間タイプの包装を使用することができます。オプション

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)) 

フォーマッタを手作業で書くこともできます。

関連する問題