What is it

dev.mccue.json provides the ability to read and write JSON data as well as to encode data into JSON and decode data from JSON.

Why use it

Most popular JSON libraries use data-binding. You make a class, possibly annotate it a little bit, and then some automatic logic binds the data inside a JSON structure to the fields of your class.

This has clear upsides, but it's hard to explain to newcomers. The underlying mechanism of data-binding is either reflection or compile-time code generation. Both are processes that are hard to "touch." The escape hatches in libraries that assume data-binding is the default mode of operation are less than ergonomic.

This takes the other approach, making people manually extract data from JSON, but does so in a way that is composable. You have to write more code, but the mechanics of the code are more plain to see.

I've written about this before. I'm listing it here because some libraries I wrote that I'll introduce later depend on it.

Getting Started

import dev.mccue.json.Json;
import dev.mccue.json.JsonDecoder;
import dev.mccue.json.JsonEncodable;

record Superhero(String name) implements JsonEncodable {
    public Json toJson() {
        return Json.objectBuilder()
            .put("name", name)
    public static Superhero fromJson(Json json) {
        return new Superhero(
            JsonDecoder.field(json, "name", JsonDecoder::string)

void main() {
    var superhero = new Superhero("superman");
    var json = superhero.toJson();
    var jsonStr = Json.writeString(json);
    var roundTripped = Json.readString(jsonStr);
    var newSuperhero = Superhero.fromJson(roundTripped);

<- Index