Skip to content

rover-app/jetted

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Jetted: Generate code from JSON Typedef schemas

JSON Type Definition, aka RFC8927, is an easy-to-learn, standardized way to define a schema for JSON data. You can use JSON Typedef to portably validate data across programming languages, create dummy data, generate code, and more.

Jetted is a fork of the original jtd-codegen project, which has not seen any updates since 2021, and appears to be abandoned. The project was forked at commit a42555d, at which point the project was MIT-licensed. We intend to continue development of Jetted under the MIT license.

We'd like to thank the original authors of jtd-codegen for their work on this project.

Differences from jtd-codegen

Rust

  • Added additional traits to generated Rust types to support cloning, equivalence, ordering, etc.
  • Changed field names to be snake_case instead of camelCase.

What is jetted?

jetted is a CLI tool that generates code bindings in many different programming languages from JSON Typedef schemas. For example, from this JSON Typedef schema:

{
    "properties": {
        "name": { "type": "string" },
        "isAdmin": { "type": "boolean" },
        "favoriteNumbers": { "elements": { "type": "float64" }}
    }
}

You can generate this TypeScript interface:

export interface User {
    favoriteNumbers: number[];
    isAdmin: boolean;
    name: string;
}

Or this Go type:

package user

type User struct {
    FavoriteNumbers []float64 `json:"favoriteNumbers"`
    IsAdmin         bool      `json:"isAdmin"`
    Name            string    `json:"name"`
}

Or types/classes/structs for any of the following programming languages:

  • C# with System.Text.Json as the JSON backend
  • Golang
  • Java with Jackson as the JSON backend
  • Python
  • Rust
  • TypeScript

With many more on the way. If you'd like a particular programming language included, please open an issue on this repo!

What is JSON Type Definition?

JSON Type Definition is a schema format for JSON data. A JSON Type Definition schema describes what is and isn't a "valid" JSON document. JSON Type Definition is easy to learn, portable (there are functionally-identical implementations across many programming languages) and standardized (the spec is set in stone as IETF RFC 8927).

Here's an example of a JSON Type Definition schema:

{
    "properties": {
        "name": {
            "type": "string"
        },
        "isAdmin": {
            "type": "boolean"
        }
    }
}

This schema considers any object with a name property (whose value must be a string), an isAdmin property (whose value must a boolean), and no other properties, to be valid.

To learn more about JSON Type Definition, check out the online documentation at jsontypedef.com.

Installation

Go to the latest jetted release on GitHub, and then install the file for your platform.

Usage

To use jetted, you first need to have a JSON Typedef schema to generate data from. Let's say you have this example data already in place:

$ cat user.jtd.json
{
    "properties": {
        "name": { "type": "string" },
        "isAdmin": { "type": "boolean" },
        "favoriteNumbers": { "elements": { "type": "float64" }}
    }
}

Then you can invoke jetted as:

# make sure you've already created the "user" directory before running this
$ jetted user.jtd.json --typescript-out user
πŸ“ Writing TypeScript code to: user
πŸ“¦ Generated TypeScript code.
πŸ“¦     Root schema converted into type: User

In that example, we generated TypeScript code. If you want to generate something else, use the appropriate "out" parameter for your desired language. For specific instructions for each programming languages, check out the documentation for:

  • C# with System.Text.Json as the JSON backend
  • Golang
  • Java with Jackson as the JSON backend
  • Python
  • TypeScript

You can produce code for multiple programming languages at once. Just pass all of the relevant parameters in the jetted invocation. For example:

$ jetted user.jtd.json --typescript-out ts-user --python-out py-user
πŸ“ Writing Python code to: py-user
πŸ“¦ Generated Python code.
πŸ“¦     Root schema converted into type: User
πŸ“ Writing TypeScript code to: ts-user
πŸ“¦ Generated TypeScript code.
πŸ“¦     Root schema converted into type: User

Advanced Usage: Adding descriptions to generated code

If you'd like to add a commented description to generated code -- for example, JavaDocs for Java code, or a docstring for Python -- jetted supports those via the description and enumDescription fields in any schema's metadata.

For example, this schema:

{
    "properties": {
        "name": {
            "metadata": {
                "description": "The user's name"
            },
            "type": "string"
        },
        "status": {
            "metadata": {
                "description": "The user's account status",
                "enumDescription": {
                    "UNVERIFIED": "The user's email has not yet been verified",
                    "VERIFIED": "The user's email has been verified",
                    "DISABLED": "The user's account was terminated"
                }
            },
            "enum": ["UNVERIFIED", "VERIFIED", "DISABLED"]
        }
    }
}

Generates into this TypeScript:

/**
 * The user's account status
 */
export type UserStatus =
    /**
     * The user's account was terminated
     */
	| "DISABLED"

    /**
     * The user's email has not yet been verified
     */
	| "UNVERIFIED"

    /**
     * The user's email has been verified
     */
	| "VERIFIED"

export interface User {
    /**
     * The user's name
     */
    name: string;

    /**
     * The user's account status
     */
    status: UserStatus;
}

Advanced Usage: Customizing jetted output

If you'd like to force jetted to use a particular type/class for some subset of your schema, you can use a "type override" property to do this. For example, if you generate TypeScript from this schema:

{
    "properties": {
        "name": {
            "metadata": {
                "typescriptType": "MyCustomNameType"
            },
            "type": "string"
        },
        "isAdmin": { "type": "boolean" },
        "favoriteNumbers": { "elements": { "type": "float64" }}
    }
}

You'll get:

export interface User {
    favoriteNumbers: number[];
    isAdmin: boolean;
    name: MyCustomNameType;
}

Each language supported by jetted supports a different set of overrides:

  • C# with System.Text.Json as the JSON backend
    • csharpSystemTextType overrides the entire outputted type
    • csharpSystemTextContainer overrides IList<T> or IDictionary<string, T> in favor of a different container type
  • Golang
    • goType overrides the entire outputted type
  • Java with Jackson as the JSON backend
    • javaJacksonType overrides the entire outputted type
    • javaJacksonContainer overrides List<T> or Map<String, T> in favor of a different container type
  • Python
    • pythonType overrides the entire outputted type
  • Rust
    • rustType overrides the entire outputted type
  • TypeScript
    • typescriptType overrides the entire outputted type

Advanced Usage: Using jetted in a larger build process

If you're using jetted as part of a larger build process (for example: if you're building an OpenAPI-like format on top of JSON Typedef), you may find it useful to programmatically get back the names of jetted-generated types. jetted supports this use-case via the --log-format CLI option.

By default, jetted uses --log-format pretty, which outputs human-friendly text to stdout. This is an example of pretty output:

πŸ“ Writing TypeScript code to: user
πŸ“¦ Generated TypeScript code.
πŸ“¦     Root schema converted into type: User
πŸ“¦     Definition "name" converted into type: Name

If instead you use --log-format minimal, then jetted outputs startup diagnostic information to stderr, and information about generated data structures to stdout:

TypeScript: writing to: user
TypeScript: root: User
TypeScript: definition: name: Name

(The first line above is to stderr, the subsequent two lines are to stdout.)

Finally, --log-format json outputs information about generated data structures to stdout as JSON. No startup information is produced:

{
  "TypeScript": {
    "out_dir": "user",
    "root_name": "User",
    "definition_names": {
      "name": "Name"
    }
  }
}

Typically speaking, --log-format minimal is easier to process in simple bash scripts. --log-format json is often easier to use from anything that's not a shell-like programming language.

About

Generate code from your JSON Typedef schemas

Resources

License

Stars

Watchers

Forks

Packages

No packages published