In the process of upgrading from 6.1a.x to 6.2-RC2, I'm observing some surprising (to me at least) results upon decoding Option
s...
import argonaut._, Argonaut._
case class Foo(a: String)
implicit val fooDecodeJson: DecodeJson[Foo] = jdecode1L(Foo(_: String))("a")
"{}".decodeEither[Option[Foo]]
// 6.a.x: results in a \/-(None)
// 6.2-RC2: results in a Left(Attempt to decode value on failed cursor.: CursorHistory(List(El(CursorOpDownField(a),false))))
Is this intended behavior? If so, how should optional fields be encoded?
Which is good. I'm glad that fix got in. The difference in behavior was just surprising upon upgrade.
I would encourage those (myself included) who are "cheating" and decoding sum types by pattern matching against tuples of Option
s to properly decode your sum types with the DecodeJson
and DecodeResult
|||
combinator.
Option[Foo]
package argonaut
import argonaut._
import argonaut.Argonaut._
import scalaz._
import Scalaz._
object parser {
case class Course (
id: Int
, teachingCenter_id: Int
, name: String
, cycle: String
, materials: Option[List[String]]
)
object Course {
implicit def CourseCodecJson: CodecJson[Course ] =
Argonaut.casecodec5(Course .apply, Course .unapply)(
"id"
, "teachingCenter_id"
,"name"
,"cycle"
,"materials"
)
}
val res = """[{"id":3,"name":"Math 101","cycle":"First","materials":[],"teachingCenterId":1}]"""
//> res : String = [{"id":3,"name":"Math 101","cycle":"First","materials":[],"t
//| eachingCenterId":1}]
res.decodeOption[List[Course]] //> res0: Option[List[argonaut.parser.Course]] = None
res.parse match {
case \/-(j) => (+j).\\.flatMap(_.--\("materials")).map( (c:Cursor) => c.focus) == Some(jEmptyArray)
case -\/(s) => s
} //> res1: Any = true
}
trait Blah[A] {
def blah(a: A): A
}
case class StringBlah[String]() {
def blah(a: String) = a.toUpperCase
}
implicit val
in scope if I want that syntax to be available outside a module that does the right import?
myFoo.asJson
.
object Foo extends argonaut.JsonIdentitys
import MyCodecs._
in client code, and have automatic case class codec derivation, etc. "just work."
I assume it's a very deliberate design decision, but I was surprised to discover that Argonaut allows Json numbers to be quoted in the Json (which would technically make them Json strings). For example:
scala> import argonaut._
import argonaut._
scala> import Argonaut._
import Argonaut._
scala> val noQuoteNum = "1"
noQuoteNum: String = 1
scala> val quotedNum = """"1""""
quotedNum: String = "1"
scala> noQuoteNum.decodeOption[Int]
res0: Option[Int] = Some(1)
scala> quotedNum.decodeOption[Int]
res1: Option[Int] = Some(1)
Can anyone shed any light on why this behavior was considered desirable for me...?
case class Person(id: String, money: Double)
i am using Argonaut to allow this entity to be serializable to json. However when i add the codec an evaluate the asJson, i get the money value as scientific notation. Is there any way to avoid this scientific notation?
\/
rather than Either
but unsure how to proceed.