Play 2.3 recording options with Json.obj and getOrElse

From the activator console, this works:

scala> import play.api.libs.json._ import play.api.libs.json._ scala> val testVal = Some("foo") testVal: Some[String] = Some(foo) scala> Json.obj("myJson" -> testVal) res0: play.api.libs.json.JsObject = {"myJson":"foo"} 

This also works:

 scala> Json.obj("myJson" -> testVal.get) res3: play.api.libs.json.JsObject = {"myJson":"foo"} 

This fails:

 scala> Json.obj("myJson" -> testVal.getOrElse("")) <console>:12: error: type mismatch; found : Object required: play.api.libs.json.Json.JsValueWrapper Json.obj("myJson" -> testVal.getOrElse("")) 

But it works:

 scala> val testVal2 = testVal.getOrElse("") testVal2: String = foo scala> Json.obj("myJson" -> testVal2) res2: play.api.libs.json.JsObject = {"myJson":"foo"} 

Why does the compiler reject my third example? testVal.getOrElse("") evaluates the string, so why does the compiler consider this to be Object in the third example above?

+6
source share
2 answers

The arguments to Json.obj repeated (String, JsValueWrapper) s. When you pass some variable, the compiler will try to implicitly convert your type to JsValueWrapper using the transforms defined in the Play JSON library (or Writes for your types).

The problem here is the contravariance of getOrElse . Since the signature of getOrElse is this:

 def getOrElse[B >: A](default: ⇒ B): B 

This means that if you have Option[String] , you can specify a value of getOrElse that is not String , and Option[String] will most likely become Option[Any] . Because of this feature, the compiler does not look for implicit conversion in JsValueWrapper , and it does not work.

The problem goes away if you use fold in Option , which is invariant:

 scala> val testVal = Some("foo") testVal: Some[String] = Some(foo) scala> Json.obj("myJson" -> testVal.fold("")(identity)) res7: play.api.libs.json.JsObject = {"myJson":"foo"} 
+5
source

You can also help getOrElse to directly determine its return type.

 Json.obj("myJson" -> testVal.getOrElse[String]("")) 
+5
source

Source: https://habr.com/ru/post/979467/


All Articles