GenSON

A Python library and CLI that generates and merges JSON Schema from sample objects and existing schemas.

Library
PyPI
v1.4.0
728stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
67/100Good
Development Activity68
Maintenance48
Community64
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
72/100Good
Architecture82
Code Quality88
Innovation62
Learning Curve55

GenSON is a Python library for generating JSON Schema from example data. Its core SchemaBuilder class accepts any number of JSON objects and/or existing schemas and merges them into a single schema that validates every input it was given, while staying as strict as that guarantee allows. It was built to describe the common structure of a large batch of JSON documents rather than to validate a single known shape.

What sets GenSON apart from a typical schema inferencer is its merge model: two object inputs combine into one object schema with the union of their properties, and two array or scalar inputs unify their type list, rather than producing an anyOf for every observed variation. anyOf only appears when GenSON hits genuinely incompatible structures, such as an object versus an array at the same position. The library implements a deliberately small, well-defined subset of JSON Schema (Draft 6+): $schema, type, items, properties, patternProperties, required, anyOf, and enum (with a seed schema), which keeps its output predictable instead of guessing at a data model it can’t know.

Beyond the Python API, the package installs a genson console script that reads JSON objects and/or schema files from stdin or disk and prints a merged schema, making it usable as a one-off CLI tool in shell pipelines as well as an importable library.

What You Get

  • A SchemaBuilder class that accumulates objects and schemas via add_object()/add_schema() and emits the merged result via to_schema()/to_json()
  • A genson CLI executable that merges JSON files (or stdin) into one schema, with delimiter auto-detection for concatenated inputs
  • Seed-schema support to opt into tuple-style array validation or patternProperties-based property matching, overriding GenSON’s default choices
  • An extensible strategy system (EXTRA_STRATEGIES on a SchemaBuilder subclass) for adding or overriding how specific JSON types are handled
  • Schema-to-schema equality checks (SchemaBuilder.__eq__) for comparing generated schemas directly

Common Use Cases

  • Bootstrapping a JSON Schema from a corpus of real API responses or log records instead of writing one by hand
  • Merging schemas from multiple API versions or optional response shapes into one schema that covers all of them
  • Piping sample payloads through the genson CLI in a shell script to regenerate a schema whenever fixture data changes
  • Seeding required/optional field detection by feeding a builder many real-world examples so required reflects only fields present in every sample

Under The Hood

Architecture Execution starts at SchemaBuilder, a thin wrapper that owns a $schema URI and a root SchemaNode. Every add_object/add_schema call delegates to that node, which in turn asks each registered SchemaStrategy subclass (in genson/schema/strategies/) whether it matches the incoming object or schema fragment via match_object/match_schema, then hands ownership to the first match. Object and array strategies recurse by holding their own child SchemaNode instances per property or item position, so the merge process is a tree of strategy objects mirroring the shape of the accumulated data. A metaclass (_MetaSchemaBuilder) builds a custom SchemaNode subclass per SchemaBuilder subclass so that EXTRA_STRATEGIES extensions compose cleanly through inheritance. If the core _get_strategy_for_ dispatch or the Typeless fallback strategy changed, every downstream type-specific strategy would break, since they all rely on that single matching contract.

Tech Stack GenSON is pure-Python (Python 3.10+ per setup.cfg), with zero runtime dependencies — only json, argparse, re, and warnings from the standard library. Packaging uses setuptools via pyproject.toml plus setup.cfg metadata, with a console_scripts entry point (genson = genson.__main__:main) that installs the CLI. Test dependencies are jsonschema (for validating generated schemas) and coverage. CI runs the matrix across Python 3.10 through 3.14 on GitHub Actions, running coverage run -m unittest with a --fail-under=90 coverage gate, plus a separate flake8 lint job.

Code Quality The test suite (test/) is substantial relative to the codebase, spread across focused files like test_add_single.py, test_add_multi.py, test_seed_schema.py, test_custom.py, and test_bin.py for the CLI, using Python’s built-in unittest. CI enforces a 90% coverage floor, and a test_docs.py file specifically re-runs the doctest-style examples embedded in README.rst against readme_renderer, so the documented API stays verified against actual behavior. Error handling is explicit and typed: a dedicated SchemaGenerationError(RuntimeError) is raised when no strategy matches an input, and warn() is used deliberately for soft-incompatibility cases (e.g. conflicting keyword values) rather than silently swallowing them. Naming is consistent (match_schema/match_object, add_schema/add_object mirrored across every strategy), and flake8 enforces style in CI.

What Makes It Unique Most JSON-to-schema inference tools produce a schema for a single sample or fall back to anyOf the moment two inputs disagree. GenSON’s differentiator is its merge-first design: the Object and scalar strategies fold new inputs into existing properties/type sets in place, so an arbitrarily large stream of examples converges to one schema instead of an ever-growing anyOf list, only branching to anyOf when types are fundamentally incompatible (e.g. object vs. array). The seed-schema mechanism is also distinctive: rather than exposing configuration flags, GenSON lets you “prime” ambiguous decisions (list vs. tuple array validation, patternProperties vs. properties) by feeding it an intentionally partial or even technically invalid schema fragment, which it then uses purely as a steering signal.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search