Inspired by schema-first ORM tooling, Nomos applies code generation to JSON-heavy Scala systems, where models, serialization, and validation are often maintained separately. Define the JSON structure once, then generate the code that represents, reads, writes, and validates it.
A single declarative JSON template produces:
- typed Scala models
- JSON codecs with no runtime dependency beyond the Scala standard library
- runtime structural validation against the embedded template
- precise errors that identify the failing JSON path
- extension points for domain validators, string formats, and serialization adapters
The goal is not to be an ORM or a general-purpose JSON library. Nomos is a build-time source generator: it keeps Scala types, serialization behavior, and runtime validation derived from the same template so they cannot drift independently.
Nomos targets Java 8 bytecode (build with JDK 11+; CI verifies Java 11 and 17). Manage versions with the BOM, depend on the runtime, and add the plugin to generate at build time. Centralize the version in a property so a bump is a single edit:
<properties>
<nomos.version>0.0.1-alpha11</nomos.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.cjfravel</groupId>
<artifactId>nomos-bom</artifactId>
<version>${nomos.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.cjfravel</groupId>
<artifactId>nomos-runtime</artifactId>
</dependency>
</dependencies>
<plugin>
<groupId>dev.cjfravel</groupId>
<artifactId>nomos-maven-plugin</artifactId>
<version>${nomos.version}</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals><goal>generate</goal></goals>
</execution>
</executions>
</plugin>A template at src/main/resources/nomos/templates/com/example/models/user.json (the base package
is derived from the path):
{
"definitions": [
{ "name": "User", "subPackage": "user",
"template": { "id": "string", "email": "string", "age": { "$optional": "number" } } }
]
}generates a matching case class that can validate, serialize, and deserialize JSON:
import com.example.models.user.User
User.fromJson("""{"id":"123","email":"j@x.com"}""") // Either[String, User]
User.validate("""{"id":"123","email":"j@x.com"}""") match {
case Right(user) => println(user)
case Left(errors) => errors.foreach(println)
}Everything lives on the docs site:
- Getting Started — install, add the plugin, generate your first types
- Template Format — fields, optionals, defaults, discriminated unions, enums
- Code Generation — what nomos emits and how to use it
- Validation — runtime validation against the embedded template
- Maven Plugin — plugin goals and configuration
nomos-runtime provides the JSON model that generated code uses: a first-party,
public, supported, intentionally minimal immutable tree in dev.cjfravel.nomos.json with
parse/write, typed accessors, and single-level transforms. It is not a general-purpose JSON
toolkit (no path queries, streaming, schema, or reflection mapping). See the
JsonValue Scaladoc
for the full contract, or browse the complete API reference.
A complete, runnable example project is in nomos-example/:
mvn -f nomos-example/pom.xml test # regenerates via the installed plugin, then runs the testsBuild and test the reactor (BOM, runtime, core, plugin), then the example separately (the end-to-end plugin path, which the reactor excludes):
mvn clean install -Dgpg.skip=true
mvn -f nomos-example/pom.xml clean testMore in the contributor guide.
Nomos is source-available under the MIT License with a SaaS provision. These are custom terms rather than the standard OSI MIT License, so GitHub and automated scanners may classify the license as “Other.” © 2026 CJ Fravel.