home

Scala and the visitor pattern

Scala provides a handful of language features that are designed to make it easy for users to define and work with algebraic data types (ADTs). You write some case classes that extend a sealed trait, you write some functions that pattern match on those case classes, and you're done: you have a nice linked list or rose tree or whatever.

Sometimes you can't use case classes to implement your variants, though, or you don't want to put your case classes in your public API, and in these situations pattern matching is typically much less useful. This blog post is about the visitor pattern, which is an alternative to pattern matching that provides many of its benefits, and about the use of visitors we're planning for Circe 1.0.

Continue reading

JSON numbers in circe 0.3.0

I'm publishing this article as a blog post (rather than as part of the circe documentation) because it's intended to be a discursive overview of the representation of JSON numbers in circe 0.3.0, not as an up-to-date description of the implementation in whatever the current circe version happens to be when you're reading this. For information about JSON numbers in circe versions after 0.3.0, please see the project documentation (in particular the changelogs and API docs).

Continue reading

Configuring generic derivation

This post is a kind of sequel to my previous article on type classes and generic derivation, although unfortunately there's a lot of intermediate content that should go between there and here that I haven't written yet. This post introduces a new feature in circe that I'm pretty excited about, though, so I'm not going to worry about skipping over that stuff for now.

Continue reading

Error accumulating decoders in circe

Suppose we're writing a service that accepts JSON requests and returns some kind of response. If there's a problem with a request—it's not even valid JSON, it doesn't match the schema we expect, etc.—we want to return an error, and of course it'd be nice if these errors were actually useful to the caller.

Unfortunately "useful" in this context can mean lots of different things, and the differences will usually depend at least in part on how involved a human was in creating the request. In the case of validation errors—i.e. we successfully received some JSON, but it's not a shape we understand—then if there's no human in sight, we generally only need to say something like "hey, we're not even speaking the same language, you should probably go try somewhere else". A detailed breakdown of all the reasons we don't understand the request is unlikely to be useful, so we might as well fail as fast as possible and save resources.

If on the other hand a human was responsible for the content of the request, it's possible that the caller will be able to make use of detailed information about all the problems with that content. Suppose for example that the JSON comes from a web form or spreadsheet that for whatever reason needs to be at least partially validated on the server side. In this case we probably don't want to fail fast—we want to accumulate all of the errors and send them back together, so that the human can correct them in a single pass.

Continue reading