Meandering through JSON with Optics

11 minute read Published: 2022-02-12

When working with third-party services, one is more likely than not to end up parsing a JSON document. For well-behaved APIs, documentation and examples are available, so the job usually becomes some minor variation of:

  1. Reach for the "canonical" JSON parsing library in your language
  2. Grab some example JSON and do some ad-hoc parsing of the bits you're interested in,
  3. Maybe write a class/type/module/namespace to immortalize adapting said JSON data to your domain, hopefully with accompanying tests.
  4. Think everything is okay, until some live data comes in with missing keys (or extra keys!) inconsistent types (nulls where they promised they wouldn't show up, invalid date formats, etc.)
  5. Go back to step 2 with the newfound edge cases, adapt.

Sometimes it's a quick process: couple of caveats you missed in the documentation, sometimes it's painstaking; the ability to close the loop in a fast, but robust, manner becomes invaluable: you don't want to spend days, and a lot of boilerplate, only to discover that some deep details didn't really work out. I believe a good type system and a good parser help a lot, but the last mile is all about the "getting to the bits of data relevant to your domain." Optics are my tool of choice for that.

Taking a good look at Optics

24 minute read Published: 2021-12-30

As part of my astrological forays, I built a little library that can traverse an interval of time and find significant events (changes in moon phase, a planet going retrograde/direct, ingresses into zodiac signs, transits, eclipses.) The data produced is necessarily verbose: you get back a sequence of events, and each type of event carries information about itself; in some cases, said information can be composed of further complex data (e.g. a Transit can tell you all the phases of application/separation it goes through in the interval, and each phase has a beginning and end.) To have to go through a sequence like this and pattern match and deconstruct in different ways depending on your use case seemed like a lot of annoying boilerplate that I, as a library author, could do better to help with than to just give you the types to pattern match, some good names, and a firm handshake. And this is when I realized what's so great about a popular, albeit intimidating, concept in the Haskell ecosystem: optics: the ability to build greatly upon "cheap" abstractions.