circe 0.3.0
This release again represents a change of plans—instead of waiting for Shapeless 2.3.0 and ongoing related work in #164, we've decided that it makes sense to get a stable release published before those changes happen.
0.3.0 is likely to be a relatively short-lived release, since the current plan is to release 0.4.0 as soon as possible after Shapeless 2.3.0 is out and configurable generic derivation is ready.
New modules
This release introduces a number of new modules. Two of these are near (or at) the root of the dependency tree and represent a refactoring of core functionality:
- circe-numbers is a zero-dependency module that supports more responsible representation of JSON numbers (see #189 for discussion). circe-core now depends on circe-numbers.
- circe-scalajs provides a few functions designed to make Scala.js interoperability more convenient.
The rest of the new modules provide more experimental new functionality or interoperability with other libraries:
- circe-literal provides a macro-powered JSON string interpolator and codecs for literal values.
- circe-jackson provides Jackson-powered parsing and printing.
- circe-refined provides codecs for types with refined constraints.
- circe-streaming supports streaming parsing and decoding using iteratee.io.
- circe-optics provides Monocle prisms for interacting with JSON documents.
- circe-java8 provides codecs for
java.time
types.
circe-parse has also been renamed circe-parser, but its role is unchanged.
Improved support (and decoders) for JSON numbers
The most substantial changes in behavior since 0.2 are related to the decoding of JSON numbers. One serious bug inherited from Argonaut has been fixed (it's no longer possible for user input to result in extremely computationally expensive operations on BigDecimal
values), it's no longer possible for numeric input to result in runtime exceptions, and a number of small changes have been made to the behavior of the integral decoders. For example, the following now fails instead of returning 32767
(#83):
io.circe.jawn.decode[Short]("32768")
And the following fails instead of returning 10
(#83):
io.circe.jawn.decode[Int]("10.999")
The decoders for Double
and Float
also now follow the integral decoders in attempting to parse a JSON string:
scala> io.circe.jawn.decode[Double]("\"0.1\"")
res0: cats.data.Xor[io.circe.Error,Double] = Right(0.1)
See #189 and this blog post for more details.
Accumulating decoders
The idea is introduced in this blog post: it's now possible to transform a Decoder[A]
into a new type AccumulatingDecoder[A]
that accumulates errors whenever possible (assuming the original Decoder
was defined in such a way as to support this). The behavior for ordinary decoders is completely unchanged, but it's now possible to do the following, for example:
import io.circe._, io.circe.generic.auto._
case class Foo(i: Int, s: String)
Decoder[Foo].accumulating(Json.empty.hcursor)
And get both errors instead of just the first.
Other changes
Decoder
now hasprepare
andemap
methods for transforming incoming JSON and successful results (#123).Json
now has adeepMerge
method (#172).- It's now possible to replay history (in the form of a list of operations) against a cursor (#135).
- A bug was fixed for
Json
'shashCode
(#142). - circe now depends on Cats 0.4.1 and Scala.js 0.6.7 (instead of 0.2.0 and 0.6.5), but these updates have little impact on the public API.
Deprecations
&&&
and|||
onDecoder
(and|||
onACursor
) are now deprecated in favor ofand
andor
.+
and-
onJsonObject
are being replaced byadd
andremove
.
The decoder
and encoder
methods on io.circe.generic.semiauto.DerivationHelper
are also now deprecated. Instead of the following:
import io.circe._, io.circe.generic.semiauto._
implicit val fooDecoder: Decoder[Foo] = deriveFor[Foo].decoder
implicit val fooEncoder: Encoder[Foo] = deriveFor[Foo].encoder
You'd now write:
import io.circe._, io.circe.generic.semiauto._
implicit val fooDecoder: Decoder[Foo] = deriveDecoder[Foo]
implicit val fooEncoder: Encoder[Foo] = deriveEncoder[Foo]
Or simply:
import io.circe._, io.circe.generic.semiauto._
implicit val fooDecoder: Decoder[Foo] = deriveDecoder
implicit val fooEncoder: Encoder[Foo] = deriveEncoder
All of the deprecated methods will be removed in 0.4.0.
Known issues
-
Jawn currently accepts
-.1
as a JSON number, and circe represents it as a null JSON value. This means that the following will result inNaN
, not-0.1
(the behavior in 0.2) or a decoding failure:io.circe.jawn.decode[Double]("-.1")
-
The parsing support provided by Scala.js in circe-parser is subject to the limitations of JavaScript's JSON parsing and will lose precision for values that can't be represented exactly as a double precision floating point number. (This is unchanged since 0.2.)
Contributors
Thanks to the twelve people who contributed code and documentation to this release, and to the many, many others who filed issues or offered feedback on Gitter.