Getting Started
Install Nomos, write a template, generate Scala code at build time, and validate JSON against it — all from one source of truth.
Installation
Nomos is a multi-module Maven project. Import the BOM to align versions, then depend on nomos-runtime — the small library the generated code uses at runtime, with no third-party JSON dependencies and only the Scala standard library required.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.cjfravel</groupId>
<artifactId>nomos-bom</artifactId>
<version>0.0.1-alpha11</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.cjfravel</groupId>
<artifactId>nomos-runtime</artifactId>
</dependency>
</dependencies>
Add the Maven plugin
The plugin scans your templates and generates sources during the generate-sources phase.
<plugin>
<groupId>dev.cjfravel</groupId>
<artifactId>nomos-maven-plugin</artifactId>
<version>0.0.1-alpha11</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals><goal>generate</goal></goals>
</execution>
</executions>
</plugin>
Write a template
Templates live under src/main/resources/nomos/templates/, and the base
package is derived from the file's path. A template at
nomos/templates/com/example/models/user.json generates into base package
com.example.models.
{
"definitions": [
{
"name": "User",
"subPackage": "user",
"template": {
"id": "string",
"username": { "type": "string", "minLength": 1 },
"email": { "type": "string", "format": "email" },
"age": { "$optional": "int" },
"roles": ["string"]
}
}
]
}
The base package comes from the template's path, and validation targets a definition by its fully-qualified name.
Generate
mvn generate-sources
Nomos writes, into target/generated-sources/nomos by default (Maven adds it as a compile source root, so it needn't be checked in):
target/generated-sources/nomos/com/example/models/user/User.scala— the case class plus a companion withfromJson,toJson, andvalidate.target/generated-sources/nomos/com/example/models/NomosFormats.scala— the embedded template and a validator built from it.
// Code generated by Nomos. DO NOT EDIT.
// Source: com/example/models/user.json
package com.example.models.user
case class User(
id: String,
username: String,
email: String,
age: Option[Int],
roles: List[String]
)
object User {
def fromJson(json: String): Either[String, User] = { ... }
def toJson(obj: User): String = { ... }
def validate(json: String): Either[List[ValidationError], User] = { ... }
}
Use the generated code
import com.example.models.user.User
// Validate against the embedded template, then parse
User.validate("""{"id":"1","username":"jo","email":"jo@x.com","roles":["admin"]}""") match {
case Right(user) => println(s"ok: ${user.email}")
case Left(errors) => errors.foreach(e => println(e.fullMessage))
}
// Round-trip
val json = User.toJson(User("1", "jo", "jo@x.com", Some(30), List("admin")))
val back = User.fromJson(json) // Either[String, User]
Validation needs no template file at runtime — the template is embedded in NomosFormats, so a single generated jar carries both the model and its schema.
What to read next
- Template Format — every type, constraint, and discriminator option.
- Validation — embedded validation plus custom validators, formats, and adapters.
- Code Generation — what gets emitted and how to tune it.
- Maven Plugin — multi-file projects and output options.