propensive / rapture

Rapture
183 stars 39 forks source link

Problem in json-parsing case classes with optional fields: #240

Open johannegger opened 7 years ago

johannegger commented 7 years ago

this code shows the problem:

import rapture.core.modes.returnTry._
case class Foo(value:Option[Int])
val ser = Json.format(Json(true))   //String = "true"
Json.parse(ser).flatMap(_.as[Foo]) //result is: Success(Bar(None))

The parser gets a string and decides that it is a valid Foo. Imho it should fail since the type is Boolean and not Object. I tested it with the jawn and the circe backend but i think the problem lies deeper.

malcolmgreaves commented 7 years ago

I have encountered a similar problem with serializing Option values using the JSON module. This code demonstrates the problem:

import rapture._
import rapture.json._
import rapture.json.jsonBackends.jawn._

val o: Option[String] = Some("hello world")
val x = Json(o)

Instead of the expected result, which should be a string encoding the Option value o. I get the following compilation warning:

warning: dead code following this construct
       val x = Json(o)
                   ^
error: No warnings can be incurred under -Xfatal-warnings.

Re-producable using the following in a build.sbt:

scalaVersion := "2.11.8"
libraryDependencies ++= Seq("com.propensive" && "rapture" % "2.0.0-M9")

Perhaps there's a type inference error going on in the JSON encoding code? This kind of thing can happen when a type is inferred as Nothing. Anything that comes after an expression that evaluates to Nothing won't be evaluated, as Nothing implies that the program will have either (a) halted or (b) continue to run in an infinite loop upon evaluating this type of expression.

For reference, if I use "com.propensive" %% "rapture-json-jawn" % "2.0.0-M3" instead, and I run the exact same code, I get the correct, expected result: res0: rapture.json.Json = "hello world"

@propensive I would love to hear your thoughts on this bug.