CJM v0.5.2

Build-time Metadata Compiler for Modern C++

Metadata compiler for Modern C++.

Write ordinary C++ models and generate recursive JSON Schema artifacts from the same normalized Metadata IR that drives C++ integration. CJM v0.5.2 also lays the documented runtime-semantics foundation for future high-performance JSON backends.

Same-name fields still default to exact C++ names, while explicit JSON metadata remains for renames, omitempty, and ignored fields. CJM is not a JSON library, schema-first generator, OpenAPI framework, or runtime validator.

Standard C++ in. Standard C++ out. Developers keep C++ models as the source of truth while CJM handles the repetitive integration code.

C++ Metadata IR Default mapping Recursive schema Runtime foundation
Latest v0.5.2
Verification 32/32 tests
Schema Draft 2020-12
user.hpp C++ Frontend
stable contract Metadata IR
backends nlohmann/json + Schema
user.hpp
enum class Status { Active, Disabled };

struct Address {
    std::string city;
};

struct User {
    std::string name;
    std::vector<Address> addresses;
    std::optional<Status> status; // json:",omitempty"
};

cjm generate \
  --input user.hpp \
  --output user.cjm.hpp

cjm generate-schema \
  --input user.hpp \
  --output user.schema.json
Input Standard C++
Workflow Stable Metadata IR
Backend nlohmann/json + recursive JSON Schema
Runtime Semantics foundation, no new backend yet

Focused early-adopter round

Early Adopters Welcome

CJM v0.5.2 is ready for early adopters who want build-time JSON integration, default field mapping, recursive JSON Schema artifacts, and documented runtime semantics for ordinary Modern C++ models.

The v0.4 public workflow has been dogfooded in a real downstream CMake project through FetchContent + cjm_generate. v0.5.0 added opt-in JSON Schema generation, v0.5.1 made same-name JSON field tags optional, and v0.5.2 expands schema coverage over recursive Metadata IR type shapes.

Try it on a practical model. If something fails or feels awkward, share the smallest header, the build command, and whether schema output or multiline declarations were involved. CJM remains a documented practical subset, not production-stable v1.0 and not a full C++ parser.

Validated downstream workflow

FetchContent FetchContent_MakeAvailable cjm_generate(...) generated *.cjm.hpp recursive generated schemas normal C++ test target

CJM's v0.4 public workflow was validated in ull-md-engine through the downstream CMake path documented on main.

The downstream coverage includes optionals, vectors, fixed-size arrays, ordered and unordered string-keyed maps, nested generated structs, enums, ignored fields, omitempty, fixed-width integers, enum string output, generated model-contract metadata, and generated to_json / from_json round trips.

Downstream quickstart

Use CJM Today

CJM v0.5.2 can be tried from a downstream CMake project with FetchContent. Packaged installation is future work, but the current release already supports the public cjm_generate workflow, default field mapping, and recursive opt-in JSON Schema generation.

1

Write ordinary C++

#pragma once

#include <optional>
#include <string>

struct User {
    std::string name;
    int age = 0;
    std::optional<std::string> nickname; // json:",omitempty"
};
2

Add CJM with FetchContent

include(FetchContent)

FetchContent_Declare(
  cxx_json_codegen
  GIT_REPOSITORY https://github.com/cjm-labs/cxx-json-codegen.git
  GIT_TAG v0.5.2
)

FetchContent_MakeAvailable(cxx_json_codegen)

add_executable(app main.cpp)
target_link_libraries(app PRIVATE nlohmann_json::nlohmann_json)
3

Generate code and schemas

cjm_generate(
  TARGET app
  HEADERS user.hpp
  GENERATED_TARGET app_cjm_generated
  GENERATE_SCHEMAS
  GENERATED_SCHEMAS_VAR app_cjm_schemas
)

Schema generation is opt-in. CJM keeps C++ headers under generated/cjm and schema artifacts under generated/schemas.

4

Include generated code

#include "user.hpp"
#include "user.cjm.hpp"

#include <nlohmann/json.hpp>

nlohmann::json json = user;
User round_trip = json.get<User>();

Include the original model header first, then the generated *.cjm.hpp header. The generated backend code provides ordinary to_json / from_json integration for nlohmann/json.

v0.5.2 notes

  • Same-name fields default to exact C++ field names; no case conversion is applied.
  • Use json:"displayName" for explicit renames, json:",omitempty" for default-name omission, and json:"-" to ignore a field.
  • JSON Schema generation now recurses through supported vectors, arrays, optionals, string-keyed maps, enums, and generated structs.
  • v0.5.2 documents runtime semantics, decode error shape, conformance fixtures, and future static backend selection.
  • Use cjm generate-schema to emit a JSON Schema artifact from a supported header.
  • Use GENERATE_SCHEMAS to opt into schema generation from cjm_generate(...).
  • Pass every related model header explicitly; CJM does not automatically discover #include dependencies yet.
  • Generated schema files are build artifacts, not C++ sources and not include-path entries.
  • Schema output is generated from validated Metadata IR, not from a separate schema-first model.

Why CJM exists

Modern C++ is powerful. Everyday boilerplate should not be the cost.

Practical schema-shaped models often need repetitive glue for JSON integration, configuration, and metadata-aware workflows.

CJM removes that repetition without replacing C++, adding runtime reflection, or asking teams to adopt a new framework.

Architecture

Compiler architecture, normal compiler workflow.

CJM sits inside the build. The parser/frontend extracts source facts, semantic analysis builds Metadata IR, and backends consume that IR to generate ordinary C++ integration code and JSON Schema artifacts.

v0.5.2 current pipeline

C++ frontend
Metadata IR
nlohmann/json + recursive JSON Schema

Long-term architecture

Source-language frontend
Language-neutral Metadata IR
Code-generation backend

What CJM does

CJM turns ordinary C++ declarations into a stable Metadata IR, then emits ordinary C++ code and JSON Schema artifacts for supported models.

  • Extracts field identity and source-level metadata from ordinary C++ declarations
  • Runs richer semantic analysis for practical model mapping
  • Defaults same-name JSON fields to exact C++ field names
  • Generates nlohmann/json integration code
  • Generates recursive JSON Schema Draft 2020-12 artifacts from Metadata IR
  • Documents runtime semantics for future JSON backend work
  • Supports opt-in schema generation through CLI and CMake
  • Keeps generated outputs inspectable build artifacts

CJM v0.5.2 — Recursive Schema and Runtime Foundation

CJM v0.5.2 extends JSON Schema generation across recursive Metadata IR type shapes and adds the design/test foundation for future static runtime backend selection.

recursive schema(T) anyOf optional schemas schema + contract + nlohmann closure runtime semantic profile static backend selection design 32/32 tests passed
Read the v0.5.2 release notes

Supported v0.5.2 scope

nlohmann/json C++ integration JSON Schema Draft 2020-12 backend explicit CMake header registration one or more explicit input headers untagged fields use exact C++ field names explicit rename tags override defaults json:",omitempty" json:"-" preserved as ignored semantics duplicate effective JSON names diagnosed supported multiline field declarations object schemas for generated structs scalar and string schema mappings fixed-width integer mappings recursive std::array<T, N> schemas std::map<std::string, T> std::unordered_map<std::string, T> recursive std::vector<T> schemas std::optional<T> via anyOf + null enum fields nested inside supported containers generated structs nested inside supported containers non-optional supported fields in required generated model-contract metadata runtime semantic profile docs decode error and path model docs runtime conformance fixture skeleton

Verification

v0.5.2 verifies recursive schema generation, recursive generated artifact closure, multiline frontend support, and the runtime foundation through the same parser/frontend -> semantic analysis -> Metadata IR pipeline.

recursive schema backend golden tests recursive nlohmann generated compile tests recursive generated model-contract tests multiline Tree-sitter and semantic tests runtime conformance skeleton checks existing CLI, CMake, parser, semantic, schema, contract tests generated-code compile tests 32/32 tests passed

Known limitations

v0.5.2 still does not add a new runtime backend. It keeps nlohmann/json as the compatibility backend while documenting the semantics future runtime backends must obey.

simdjson, Glaze, yyjson, or other high-performance runtime backends runtime JSON Schema validation native JSON backend automatic snake_case or camelCase conversion type-level opt-in metadata syntax default-value metadata OpenAPI route generation HTTP endpoint policy arbitrary JSON values std::variant / std::any pointer or polymorphic serialization custom converters custom enum string mapping policies time and datetime schema formats automatic header discovery full C++ grammar support at the CJM product level private fields install/package distribution

Principles

Engineering before magic: CJM should remain early but architecture-driven, useful for practical schema-shaped C++ JSON models, and easy to inspect.

Ordinary C++ should be enough

Users write standard C++. Generated output is standard C++. Everything in between is CJM's responsibility.

Build-time instead of runtime

No hidden runtime, no dynamic reflection engine, and no runtime cost introduced by CJM.

Visible and predictable

Generated C++ should be readable, inspectable, and debuggable when developers need to look inside.

Native to existing builds

Adding CJM should feel like enabling another compiler tool inside an existing CMake project.

Long-term vision

Code generation should feel like the build simply got smarter.

v0.5.2 generates nlohmann/json integration and recursive JSON Schema artifacts from normalized Metadata IR. The larger goal is a reusable compiler foundation for modern build-time metadata workflows in C++: simple user experience, production-quality engineering, and zero runtime overhead introduced by CJM.

CJM succeeds when developers forget that code generation is happening. They write standard C++, run their normal build, and everything works.

FAQ

CJM, in plain terms.

What is CJM?

CJM is a build-time metadata compiler for Modern C++. It reads ordinary model declarations, builds Metadata IR, and generates backend artifacts such as nlohmann/json integration and JSON Schema.

Does CJM replace nlohmann/json?

No. The current official runtime integration backend targets nlohmann/json. CJM generates model-specific integration code around your C++ models.

What does v0.5.2 add?

v0.5.2 adds recursive JSON Schema fragments for supported Metadata IR type shapes and documents runtime semantics, decode error shape, conformance fixtures, and static backend selection for future backend work.