{"id":15059536,"url":"https://github.com/dragonwasrobot/json-schema-to-elm","last_synced_at":"2025-04-13T19:10:08.197Z","repository":{"id":18318089,"uuid":"84006914","full_name":"dragonwasrobot/json-schema-to-elm","owner":"dragonwasrobot","description":"Generates Elm types, JSON decoders, JSON encoders and fuzz tests from JSON schema specifications","archived":false,"fork":false,"pushed_at":"2024-07-23T03:33:12.000Z","size":558,"stargazers_count":89,"open_issues_count":9,"forks_count":11,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-27T09:46:26.435Z","etag":null,"topics":["code-generator","elixir","elixir-lang","elm","elm-lang","json","json-decoder","json-encoder","json-schema","parser-generator"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dragonwasrobot.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-03-05T22:26:27.000Z","updated_at":"2025-03-10T02:23:30.000Z","dependencies_parsed_at":"2024-01-05T22:00:40.799Z","dependency_job_id":"8be75a41-9def-44bd-a42f-768d8f063003","html_url":"https://github.com/dragonwasrobot/json-schema-to-elm","commit_stats":{"total_commits":196,"total_committers":6,"mean_commits":"32.666666666666664","dds":0.7040816326530612,"last_synced_commit":"156a07ea3579d84506511a3eda06a5b8efa1637e"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dragonwasrobot%2Fjson-schema-to-elm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dragonwasrobot%2Fjson-schema-to-elm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dragonwasrobot%2Fjson-schema-to-elm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dragonwasrobot%2Fjson-schema-to-elm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dragonwasrobot","download_url":"https://codeload.github.com/dragonwasrobot/json-schema-to-elm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248766736,"owners_count":21158301,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["code-generator","elixir","elixir-lang","elm","elm-lang","json","json-decoder","json-encoder","json-schema","parser-generator"],"created_at":"2024-09-24T22:45:14.363Z","updated_at":"2025-04-13T19:10:08.167Z","avatar_url":"https://github.com/dragonwasrobot.png","language":"Elixir","funding_links":[],"categories":["Code generators"],"sub_categories":["Individual Podcast episodes"],"readme":"# JSON Schema to Elm\n\n### Description\n\nGenerates Elm types, JSON decoders, JSON encoders, and Fuzz tests from JSON\nschema specifications.\n\n**Only supports - a subset of - JSON Schema draft v7.**\n\n## Installation\n\nThis project requires that you already have [elixir](http://elixir-lang.org/)\nand its build tool `mix` installed, this can be done with `brew install elixir`\nor similar.\n\n- Download latest release at:\n  https://github.com/dragonwasrobot/json-schema-to-elm/releases, or\n- clone this repository:\n  `git clone git@github.com:dragonwasrobot/json-schema-to-elm.git`, then\n- build an executable: `MIX_ENV=prod mix build` (Windows `cmd.exe`: `set \"MIX_ENV=prod\" \u0026\u0026 mix build`), and\n- run the executable, `./js2e` (Windows: `escript .\\js2e`), that has now been created in your current working\n  directory.\n\n## Usage\n\nRun `./js2e` for usage instructions.\n\n\u003e Note: The `js2e` tool only tries to resolve references for the file(s) you\n\u003e pass it. So if you need to generate Elm code from more than one file you\n\u003e have to pass it the enclosing directory of the relevant JSON schema files,\n\u003e in order for it to be able to resolve the references correctly.\n\nA proper description of which properties are mandatory and how the generator\nworks is still in progress, but feel free to take a look at the `examples`\nfolder which contains an example of a pair of JSON schemas and their\ncorresponding Elm output. Likewise, representations of each of the different\nJSON schema types are described in the `lib/types` folder.\n\n## Example\n\nIf we supply `js2e` with the following JSON schema file, `definitions.json`:\n``` json\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"title\": \"Definitions\",\n    \"$id\": \"http://example.com/definitions.json\",\n    \"description\": \"Schema for common types\",\n    \"definitions\": {\n        \"color\": {\n            \"$id\": \"#color\",\n            \"type\": \"string\",\n            \"enum\": [ \"red\", \"yellow\", \"green\", \"blue\" ]\n        },\n        \"point\": {\n            \"$id\": \"#point\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"x\": {\n                    \"type\": \"number\"\n                },\n                \"y\": {\n                    \"type\": \"number\"\n                }\n            },\n            \"required\": [ \"x\", \"y\" ]\n        }\n    }\n}\n```\n\nit produces the following Elm file, `Data/Definitions.elm`:\n\n``` elm\nmodule Data.Definitions exposing\n    ( Color(..)\n    , Point\n    , colorDecoder\n    , encodeColor\n    , encodePoint\n    , pointDecoder\n    )\n\n-- Schema for common types\n\nimport Helper.Encode as Encode\nimport Json.Decode as Decode exposing (Decoder)\nimport Json.Decode.Extra as Decode\nimport Json.Decode.Pipeline\n    exposing\n        ( custom\n        , optional\n        , required\n        )\nimport Json.Encode as Encode exposing (Value)\n\n\ntype Color\n    = Red\n    | Yellow\n    | Green\n    | Blue\n\n\ntype alias Point =\n    { x : Float\n    , y : Float\n    }\n\n\ncolorDecoder : Decoder Color\ncolorDecoder =\n    Decode.string |\u003e Decode.andThen (parseColor \u003e\u003e Decode.fromResult)\n\n\nparseColor : String -\u003e Result String Color\nparseColor color =\n    case color of\n        \"red\" -\u003e\n            Ok Red\n\n        \"yellow\" -\u003e\n            Ok Yellow\n\n        \"green\" -\u003e\n            Ok Green\n\n        \"blue\" -\u003e\n            Ok Blue\n\n        _ -\u003e\n            Err \u003c| \"Unknown color type: \" ++ color\n\n\npointDecoder : Decoder Point\npointDecoder =\n    Decode.succeed Point\n        |\u003e required \"x\" Decode.float\n        |\u003e required \"y\" Decode.float\n\n\nencodeColor : Color -\u003e Value\nencodeColor color =\n    color |\u003e colorToString |\u003e Encode.string\n\n\ncolorToString : Color -\u003e String\ncolorToString color =\n    case color of\n        Red -\u003e\n            \"red\"\n\n        Yellow -\u003e\n            \"yellow\"\n\n        Green -\u003e\n            \"green\"\n\n        Blue -\u003e\n            \"blue\"\n\n\nencodePoint : Point -\u003e Value\nencodePoint point =\n    []\n        |\u003e Encode.required \"x\" point.x Encode.float\n        |\u003e Encode.required \"y\" point.y Encode.float\n        |\u003e Encode.object\n```\n\nwhich contains an Elm type for the `color` and `point` definitions along with\ntheir corresponding JSON decoders and encoders.\n\nFurthermore, if we instead supply `js2e` with a directory of JSON schema files\nthat have references across files, e.g.\n\n``` json\n{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"$id\": \"http://example.com/circle.json\",\n    \"title\": \"Circle\",\n    \"description\": \"Schema for a circle shape\",\n    \"type\": \"object\",\n    \"properties\": {\n        \"center\": {\n            \"$ref\": \"http://example.com/definitions.json#point\"\n        },\n        \"radius\": {\n            \"type\": \"number\"\n        },\n        \"color\": {\n            \"$ref\": \"http://example.com/definitions.json#color\"\n        }\n    },\n    \"required\": [\"center\", \"radius\"]\n}\n```\n\nthen the corresponding Elm file, `Data/Circle.elm`, will import the\ndefinitions (types, encoders and decoders) from the other Elm module,\n`Data/Definitions.elm`.\n\n``` elm\nmodule Data.Circle exposing\n    ( Circle\n    , circleDecoder\n    , encodeCircle\n    )\n\n-- Schema for a circle shape\n\nimport Data.Definitions as Definitions\nimport Helper.Encode as Encode\nimport Json.Decode as Decode exposing (Decoder)\nimport Json.Decode.Extra as Decode\nimport Json.Decode.Pipeline\n    exposing\n        ( custom\n        , optional\n        , required\n        )\nimport Json.Encode as Encode exposing (Value)\n\n\ntype alias Circle =\n    { center : Definitions.Point\n    , color : Maybe Definitions.Color\n    , radius : Float\n    }\n\n\ncircleDecoder : Decoder Circle\ncircleDecoder =\n    succeed Circle\n        |\u003e required \"center\" Definitions.pointDecoder\n        |\u003e optional \"color\" (Decode.nullable Definitions.colorDecoder) Nothing\n        |\u003e required \"radius\" Decode.float\n\n\nencodeCircle : Circle -\u003e Value\nencodeCircle circle =\n    []\n        |\u003e Encode.required \"center\" circle.center Definitions.encodePoint\n        |\u003e Encode.optional \"color\" circle.color Definitions.encodeColor\n        |\u003e Encode.required \"radius\" circle.radius Encode.float\n        |\u003e Encode.object\n```\n\nFurthermore, `js2e` also generates test files for the generated decoders and\nencoders to make the generated code immediately testable. The generated test\nfiles fuzzes instances of a given Elm type and tests that encoding it as JSON\nand decoding it back into Elm returns the original instance of that generated\nElm type. In the above case, the following test files,\n`tests/Data/CircleTests.elm` and `tests/Data/DefinitionsTests.elm`, are\ngenerated:\n\n``` elm\nmodule Data.CircleTests exposing\n    ( circleFuzzer\n    , encodeDecodeCircleTest\n    )\n\n\n-- Tests: Schema for a circle shape\n\nimport Data.Circle exposing (..)\nimport Data.DefinitionsTests as Definitions\nimport Expect exposing (Expectation)\nimport Fuzz exposing (Fuzzer)\nimport Json.Decode as Decode\nimport Test exposing (..)\n\n\ncircleFuzzer : Fuzzer Circle\ncircleFuzzer =\n    Fuzz.map3\n        Circle\n        Definitions.pointFuzzer\n        (Fuzz.maybe Definitions.colorFuzzer)\n        Fuzz.niceFloat\n\n\nencodeDecodeCircleTest : Test\nencodeDecodeCircleTest =\n    fuzz circleFuzzer \"can encode and decode Circle object\" \u003c|\n        \\circle -\u003e\n            circle\n                |\u003e encodeCircle\n                |\u003e Decode.decodeValue circleDecoder\n                |\u003e Expect.equal (Ok circle)\n```\nand\n\n``` elm\nmodule Data.DefinitionsTests exposing\n    ( colorFuzzer\n    , encodeDecodeColorTest\n    , encodeDecodePointTest\n    , pointFuzzer\n    )\n\n-- Tests: Schema for common types\n\nimport Data.Definitions exposing (..)\nimport Expect exposing (Expectation)\nimport Fuzz exposing (Fuzzer)\nimport Json.Decode as Decode\nimport Test exposing (..)\n\n\ncolorFuzzer : Fuzzer Color\ncolorFuzzer =\n    [ Red, Yellow, Green, Blue ]\n        |\u003e List.map Fuzz.constant\n        |\u003e Fuzz.oneOf\n\n\nencodeDecodeColorTest : Test\nencodeDecodeColorTest =\n    fuzz colorFuzzer \"can encode and decode Color object\" \u003c|\n        \\color -\u003e\n            color\n                |\u003e encodeColor\n                |\u003e Decode.decodeValue colorDecoder\n                |\u003e Expect.equal (Ok color)\n\n\npointFuzzer : Fuzzer Point\npointFuzzer =\n    Fuzz.map2\n        Point\n        Fuzz.niceFloat\n        Fuzz.niceFloat\n\n\nencodeDecodePointTest : Test\nencodeDecodePointTest =\n    fuzz pointFuzzer \"can encode and decode Point object\" \u003c|\n        \\point -\u003e\n            point\n                |\u003e encodePoint\n                |\u003e Decode.decodeValue pointDecoder\n                |\u003e Expect.equal (Ok point)\n```\n\nFinally, `js2e` also generates package config files, `package.json` and\n`elm.json`, and a `.tool-versions` file, making it easy to test that the\ngenerated Elm code is behaving as expected. Note that the `.tool-versions` file\nis not a file required by `elm` nor `elm-test` but instead a file used by the\n`asdf` version manager, https://github.com/asdf-vm/asdf, to install and run the\ncorrect compiler versions of `node` and `elm` specified in the `.tool-versions`\nfile for a given project.\n\nThus, if we supply the following directory structure to `js2e` in the above\ncase:\n\n```\n.\n└── js2e_input/\n    ├── definitions.json\n    └── circle.json\n```\n\nthe following new directory structure is generated:\n\n```\n.\n└── js2e_output/\n    ├── .tool-versions\n    ├── package.json\n    ├── elm.json\n    ├── src/\n    │   ├── Data/\n    │   │   ├── Circle.elm\n    │   │   └── Definitions.elm\n    │   └── Helper/\n    │       └── Encode.elm\n    └── tests/\n        └── Data/\n            ├── CircleTests.elm\n            └── DefinitionsTests.elm\n```\n\ncontaining the files described above along with the needed package config files\nto compile and run the tests.\n\n## Error reporting\n\nAny errors encountered by the `js2e` tool while parsing the JSON schema files or\nprinting the Elm code output, is reported in an Elm-like style, e.g.\n\n```\n--- UNKNOWN NODE TYPE -------------------------------------- all_of_example.json\n\nThe value of \"type\" at '#/allOf/0/properties/description' did not match a known node type\n\n    \"type\": \"strink\"\n            ^^^^^^^^\n\nWas expecting one of the following types\n\n    [\"null\", \"boolean\", \"object\", \"array\", \"number\", \"integer\", \"string\"]\n\nHint: See the specification section 6.25. \"Validation keywords - type\"\n\u003chttp://json-schema.org/latest/json-schema-validation.html#rfc.section.6.25\u003e\n```\n\nor\n\n```\n--- UNRESOLVED REFERENCE ----------------------------------- all_of_example.json\n\n\nThe following reference at `#/allOf/0/color` could not be resolved\n\n    \"$ref\": #/definitions/kolor\n            ^^^^^^^^^^^^^^^^^^^\n\n\nHint: See the specification section 9. \"Base URI and dereferencing\"\n\u003chttp://json-schema.org/latest/json-schema-core.html#rfc.section.9\u003e\n```\n\nIf you encounter an error while using `js2e` that does not mimic the above\nElm-like style, but instead looks like an Elixir stacktrace, please report this\nas a bug by opening an issue and including a JSON schema example that recreates\nthe error.\n\n## Contributing\n\nIf you feel like something is missing/wrong or if I've misinterpreted the JSON\nschema spec, feel free to open an issue so we can discuss a solution. Note that\nthe JSON schema parser has been moved to the new project,\nhttps://github.com/dragonwasrobot/json_schema, so this repo only implements the\nElm code generators.\n\nPlease consult `CONTRIBUTING.md` first before opening an issue.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdragonwasrobot%2Fjson-schema-to-elm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdragonwasrobot%2Fjson-schema-to-elm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdragonwasrobot%2Fjson-schema-to-elm/lists"}