JSON to Elm Type Generator
Convert JSON objects into Elm type aliases and JSON decoders instantly. Generates idiomatic Elm 0.19 code with correct type mappings, elm/json Decoder pipeline syntax, and handles nested objects, arrays, Maybe types, and custom types — paste the output directly into your Elm module.
Convert JSON objects into Elm type aliases and JSON decoders instantly. Generates idiomatic Elm 0.19 code with correct type mappings, elm/json Decoder pipeline syntax, and handles nested objects, arrays, Maybe types, and custom types — paste the output directly into your Elm module.
This tool is designed to provide a seamless experience for developers by handling complex operations directly in your browser with maximum speed and security.
Elm is a purely functional programming language that compiles to JavaScript, designed specifically for building reliable web applications. Its defining characteristic is that it guarantees no runtime exceptions — once your Elm code compiles, it will not crash with a null pointer exception, an undefined is not a function error, or a type mismatch at runtime. This guarantee comes from Elm's strict static type system, which requires that every piece of data your program handles has an explicitly declared type, and the compiler verifies at compile time that every function receives and returns the correct types.
This type safety guarantee creates a specific challenge when consuming data from external sources like REST APIs: JSON is an untyped format, and the values it contains may not match what your Elm code expects. A JSON field that your code expects to be a number might be null, might be a string, or might be absent entirely. In JavaScript, this mismatch causes a runtime exception that crashes your application. In Elm, the solution is explicit JSON decoding — you write a decoder that precisely specifies how to map each JSON field to an Elm type, and the decoder handles failure explicitly rather than crashing. If the JSON does not match the expected structure, the decoder returns an error value rather than throwing an exception. Your Elm code is forced to handle both the success and error cases.
The elm/json package provides the decoder primitives: Decode.string, Decode.int, Decode.float, Decode.bool, Decode.list, Decode.field, Decode.maybe, and the Pipeline.required, Pipeline.optional, and Pipeline.hardcoded combinators for building decoders for record types. Writing these decoders by hand is correct but tedious for large JSON structures — a JSON object with 15 fields requires 15 decoder field calls, each mapping the JSON field name to the corresponding Elm record field. This tool generates all of that boilerplate automatically from a JSON sample.
Read the Full GuideThis tool takes a JSON object and generates two things: an Elm type alias that describes the data structure, and a JSON decoder using the elm/json Pipeline syntax that maps the JSON fields to the type alias fields. For a JSON object with fields of different types, the tool infers the correct Elm type for each field — JSON strings become String, integers become Int, floats become Float, booleans become Bool, JSON arrays become List with the correct element type inferred, and null or absent values become Maybe with the inferred inner type. For nested JSON objects, the tool generates separate named type aliases and separate decoders for each nested level, then composes them correctly. A JSON field whose value is an object becomes a field of a named Elm type with its own decoder. A JSON field whose value is an array of objects becomes a List of that named Elm type, decoded using Decode.list applied to the nested type's decoder. The generated code uses the Pipeline pattern (using Json.Decode.Pipeline) which is the idiomatic Elm 0.19 approach for decoding record types — more readable and maintainable than the map2, map3, map4 approach for records with many fields. The generated code is compatible with Elm 0.19 and uses the elm/json package (version 1.1.3) which is the standard JSON library in the current Elm ecosystem. The import statements are included in the output so you can paste the generated code directly into a new Elm module or into an existing module, adjusting the module name and any type names that conflict with existing types in your codebase. Field names that are JSON snake_case (like user_id) are converted to Elm camelCase (like userId) following Elm naming conventions, with the original JSON field name preserved in the decoder's field call.
1. Paste your JSON into the Input JSON Source field — use a real API response sample that represents the complete structure you need to decode in your Elm application. A single representative JSON object works best. If your API returns an array, paste one element from the array — the generated decoder will be for a single item, and you wrap it in Decode.list when decoding the full array response.
2. Click Generate Elm Alias — the tool parses every field in your JSON, infers the Elm type for each value, generates the type alias record definition and the corresponding Json.Decode.Pipeline decoder, handles nested objects as separate named types with their own decoders, and outputs the complete Elm code including import statements in the result panel.
3. Review the generated type alias — check that the inferred Elm types are correct for your use case. JSON integers are inferred as Int. If your API returns large IDs that exceed Int's range, change those fields to Float or String. JSON null values become Maybe — verify that the fields the tool marked as Maybe are truly optional in your API, and change non-nullable fields from Maybe Type to Type and update the decoder from Pipeline.optional to Pipeline.required accordingly.
4. Check the generated decoder field names — the tool converts JSON snake_case field names to Elm camelCase (user_id becomes userId) in the type alias field names while preserving the original JSON field name in the Decode.field call. Verify the camelCase conversion looks correct and that the Decode.field string matches the exact JSON field name your API returns, including case sensitivity.
5. Copy the generated code and paste it into your Elm module — add the elm/json and NoRedInk/elm-json-decode-pipeline packages to your elm.json dependencies if they are not already present (elm install elm/json and elm install NoRedInk/elm-json-decode-pipeline), then compile. The Elm compiler will report any type mismatches or missing fields immediately.
The biggest friction point when integrating a new REST API into an Elm application is writing the type definitions and decoders. It is not conceptually difficult — once you understand the decoder pattern, writing decoders is mechanical. But mechanical means time-consuming and error-prone. A JSON response with 20 fields across three nested objects means writing three type aliases with 20 fields total and three decoders with 20 field calls. Getting the field names exactly right, mapping the right types, composing the nested decoders correctly — any mistake causes a decoder error at runtime that requires tracing through the decoder to find where the mismatch is. This tool eliminates that mechanical work. The workflow with this tool is: call the API endpoint in a browser or Postman, copy the JSON response, paste it here, get the type alias and decoder, paste into your Elm module, compile. The compiler will immediately tell you about any fields you reference in your Elm code that are not present in the generated type alias — which is exactly the kind of feedback that makes Elm so productive. You spend your time on application logic rather than on decoder boilerplate. Elm's decoder pattern is also valuable as documentation and understanding. When you generate the decoder for an API response, you get an explicit record of exactly which fields the decoder expects, what type each field must be, and which fields are optional (Maybe) versus required. This is information that is implicit and invisible in JavaScript — you discover it by running the code and seeing what crashes. In Elm it is explicit and checked by the compiler. The generated decoders serve as living documentation of what your application expects from the API, and the compiler enforces it.
Elm 0.19 compatible — generates code using the current elm/json 1.1.3 package and the NoRedInk elm-json-decode-pipeline library which is the standard decoder approach in the current Elm ecosystem
Pipeline decoder syntax — generates the idiomatic Pipeline pattern (Decode.succeed Type |> Pipeline.required ...) which is more readable than the map2 map3 map4 approach for records with more than two fields
Correct type inference — JSON strings become String
integers become Int
floats become Float
booleans become Bool
arrays become List with the correct element type
and null values become Maybe
Nested type decomposition — generates separate named type aliases and decoders for each nested JSON object and composes them correctly in the parent decoder
snake_case to camelCase conversion — converts JSON field names like user_id to Elm field names like userId while preserving the original JSON key in the Decode.field call
Complete module output — generated code includes module declaration and import statements so you can paste it directly into a new Elm file
100% browser-based — your JSON API response data never leaves your machine and is never transmitted to any server
Instant generation — all type inference and code generation runs locally in your browser with no server round-trip
Generating Elm type aliases and decoders for REST API responses when building Elm single-page applications
Bootstrapping JSON decoding code for third-party API integrations without an official Elm package
Creating decoder boilerplate for Elm Http.get and Http.post response handling
Generating type definitions for JSON data stored in ports that passes between Elm and JavaScript
Converting JSON configuration structures into Elm type aliases for application settings
Generating decoders for WebSocket message payloads received as JSON strings in Elm applications
Creating Elm type definitions for JSON stored in localStorage and retrieved via ports
Learning the elm/json decoder Pipeline pattern by seeing generated code for different JSON structures
Example Input
{
"id": 1,
"name": "Priya Singh",
"email": "priya@learnhubly.com",
"isActive": true,
"tags": ["developer", "admin"],
"profile": {
"bio": "Principal Software Engineer",
"skills": ["Go", "React", "TypeScript"]
}
}Example Output
module Data.User exposing (User, Profile, userDecoder, profileDecoder)
import Json.Decode as Decode exposing (Decoder)
import Json.Decode.Pipeline as Pipeline
type alias Profile =
{ bio : String
, skills : List String
}
type alias User =
{ id : Int
, name : String
, email : String
, isActive : Bool
, tags : List String
, profile : Profile
}
profileDecoder : Decoder Profile
profileDecoder =
Decode.succeed Profile
|> Pipeline.required "bio" Decode.string
|> Pipeline.required "skills" (Decode.list Decode.string)
userDecoder : Decoder User
userDecoder =
Decode.succeed User
|> Pipeline.required "id" Decode.int
|> Pipeline.required "name" Decode.string
|> Pipeline.required "email" Decode.string
|> Pipeline.required "isActive" Decode.bool
|> Pipeline.required "tags" (Decode.list Decode.string)
|> Pipeline.required "profile" profileDecoderDecoder Complexity for Deeply Nested JSON: Highly nested JSON structures — objects five or six levels deep or polymorphic arrays where different array elements have different shapes — generate deeply nested type aliases and decoders that may need manual refinement. The tool breaks nested structures into separate named types which is correct, but for very complex nested JSON the generated type names (NestedObject, NestedNestedObject) may need to be renamed to more meaningful names that reflect your domain model. Review all generated type names and rename them to match your application's terminology before using the code.
Missing elm-json-decode-pipeline Package: The generated decoders use the NoRedInk/elm-json-decode-pipeline package for the Pipeline syntax. If this package is not in your elm.json dependencies, the generated code will fail to compile. Install it with: elm install NoRedInk/elm-json-decode-pipeline. The elm/json package itself is a core Elm package and is included by default in all Elm projects — only the pipeline package needs to be installed separately.
Int Overflow for Large Numeric IDs: Elm's Int type is a 32-bit integer on 32-bit platforms and a JavaScript number (53-bit safe integer) on 64-bit platforms in Elm 0.19 compiled to JavaScript. If your API returns numeric IDs larger than 2^53 (such as Twitter snowflake IDs), those IDs will lose precision when decoded as Int. For large numeric IDs, change the generated Int type to String in the type alias and change the Decode.int call to Decode.string in the decoder. Many APIs that use large IDs also offer a string version of the same ID field for this reason.
JSON null Fields Decoded as Maybe When They Should Be Required: The tool generates Maybe Type for JSON fields that appear as null in your sample. If a field is null in the specific response sample you pasted but is actually always present and non-null in real responses, the generated Maybe is incorrect. Change Maybe String to String and Pipeline.optional to Pipeline.required for fields you know are always present. Conversely, if a field appears with a value in your sample but is sometimes absent in real responses, change the generated Pipeline.required to Pipeline.optional with a default value.
Type Name Conflicts with Existing Elm Modules: The generated type alias names are derived from the JSON structure — a top-level object becomes a type named after the module, nested objects get generated names. If these names conflict with existing types in your Elm codebase, you will see a compile error about duplicate type definitions. Rename the conflicting generated types before pasting the code into your module. Elm type names must start with an uppercase letter and be unique within a module.
Using the generated decoder directly without handling the Result type from Http.get
Fix: When you use a decoder with Elm's Http.get, the result arrives in your update function as a Msg with a Result Http.Error YourType value. The Result type has two variants: Ok YourType for a successful decode and Err Http.Error for any failure — network error, non-200 status, or JSON decode failure. You must handle both cases in your update function's case expression. A common mistake is pattern matching only on Ok and using a wildcard _ for the error case, which silently discards decode errors and makes debugging impossible. Handle the Err case explicitly and store the error in your model so you can display it or log it.
Generating the decoder from a response sample that does not represent the full data shape
Fix: If your JSON response sample is a minimal example with only required fields, the generated decoder will not include fields that are optional or absent in your sample but present in real responses. The generated type alias will be missing those fields, and when your application receives a real response with extra fields, the decoder ignores them silently (Elm decoders ignore unknown fields by default) — but your application logic cannot access those fields because they are not in the type alias. Use the most complete API response sample you can get — one that includes all optional fields with their values populated — to generate the most complete type alias.
Treating Elm's Maybe type like JavaScript's null and accessing the inner value without checking
Fix: In Elm, a Maybe Type value is either Just value or Nothing. To use the inner value, you must explicitly handle both cases using Maybe.withDefault, Maybe.map, case expression, or similar. There is no way to access the inner value of a Maybe without handling the Nothing case — Elm's type system enforces this at compile time. A common mistake for developers coming from JavaScript is thinking of Maybe as optionally null and expecting to pass it where a non-Maybe value is expected. If the Elm compiler reports a type mismatch between Maybe String and String, add Maybe.withDefault '' or use a case expression to handle the Nothing case before passing the value.
Not understanding that Elm decoders are composable values, not functions that are called imperatively
Fix: In Elm, a Decoder String is a value that describes how to decode a JSON value into a String — it is not a function you call directly. You pass a decoder to Json.Decode.decodeString or Json.Decode.decodeValue or Http.get's expect parameter. The decoder handles the JSON parsing internally. A common mistake is trying to call userDecoder on a string directly rather than passing it to decodeString. The correct pattern is: case Json.Decode.decodeString userDecoder jsonString of Ok user -> ... Err error -> .... The decoder is the strategy, and decodeString is the function that applies the strategy to a JSON string.
Using the generated decoder with a different Elm version than 0.19
Fix: The generated code targets Elm 0.19 and uses the elm/json package API available in 0.19. The Pipeline syntax (Json.Decode.Pipeline) is from the NoRedInk/elm-json-decode-pipeline package which targets Elm 0.19. If you are on an older Elm version (0.18 or earlier), the package names, import paths, and some API functions are different — elm-community/json-extra in 0.18 has a different decoder composition API. If you are maintaining a legacy Elm 0.18 project, you will need to adapt the generated code to the 0.18 API. For new projects, always use Elm 0.19 — it is the current stable version and the only version with active package ecosystem support.
JSON Cheatsheet
Interactive reference guide for valid JSON syntax, data types, parsing/stringifying methods, schema validation rules, and language integrations.
Regex Cheatsheet
Interactive guide to Regex anchors, character classes, quantifiers, lookarounds, capturing groups, and search flags.
HTTP Headers Cheatsheet
Complete guide to standard and security HTTP headers including Authorization, CORS control, caching policies, and CSP directives.
SQL Cheatsheet
Complete guide to SQL statements including SELECT queries, WHERE filters, aggregate functions, JOIN types, and DDL commands.
Does it support Elm 0.19?
Yes. The generated code is fully compatible with Elm 0.19 and uses the elm/json package (version 1.1.3) which is the standard JSON library in the current Elm ecosystem. The Pipeline decoder syntax uses NoRedInk/elm-json-decode-pipeline which is the community-standard package for decoding record types in Elm 0.19. Elm 0.19 is the current stable version of Elm and has been since August 2019. All new Elm projects should use 0.19.
What is a JSON decoder in Elm?
A JSON decoder in Elm is a value of type Decoder a that describes how to convert a raw JSON value into an Elm value of type a. Unlike JavaScript where JSON.parse() returns a loosely-typed object that can fail at runtime when you access fields that do not exist, Elm's JSON decoders are explicit and handle failure as a value — decoding either succeeds and returns Ok value or fails and returns Err String describing what went wrong. This explicit failure handling is what allows Elm to guarantee no runtime exceptions even when consuming external JSON data from APIs that might change their response structure.
What is the difference between Pipeline.required and Pipeline.optional?
Pipeline.required decodes a field that must be present in the JSON and must not be null — if the field is absent or null, the entire decoder fails with an error. Pipeline.optional decodes a field that may be absent or null — if the field is missing or null, it uses the provided default value instead of failing. The tool generates Pipeline.required for fields that have a non-null value in your JSON sample, and Pipeline.optional for fields that appear as null. Review these carefully against the actual API contract — a field that was non-null in your sample but is sometimes null in real responses should use Pipeline.optional with an appropriate default or Maybe.
How do I decode a JSON array of objects at the top level?
If the API returns a top-level JSON array rather than a single object, use Decode.list applied to the generated decoder: Decode.list userDecoder. This tells Elm to expect a JSON array and decode each element using userDecoder, producing a List User on success. In an Http.get call: Http.get { url = apiUrl, expect = Http.expectJson GotUsers (Decode.list userDecoder) }. The generated decoder from this tool is for a single item — wrapping it in Decode.list handles the array case.
What packages do I need to install?
The generated code requires two packages: elm/json which is a core Elm package included in all Elm projects by default, and NoRedInk/elm-json-decode-pipeline for the Pipeline syntax. Install the pipeline package with: elm install NoRedInk/elm-json-decode-pipeline. This adds it to your elm.json dependencies automatically. If you prefer not to use a third-party package, you can replace the Pipeline syntax with manual Decode.map2, Decode.map3 etc. calls, though this becomes verbose for records with more than about four fields.
Why does Elm require explicit JSON decoders when other languages don't?
Most languages with automatic JSON serialization — Python, JavaScript, C# with System.Text.Json — use reflection or runtime type information to map JSON fields to object properties automatically. Elm does not have runtime reflection, and its type system operates entirely at compile time. The trade-off is that JSON parsing failures are handled explicitly and caught by the type system rather than causing runtime exceptions. In JavaScript, accessing a JSON field that does not exist returns undefined which then propagates through your code causing errors far from the source. In Elm, the decoder fails at the boundary where JSON enters your application, the failure is a typed value you must handle, and errors never propagate silently.
Can I use the generated decoder with Elm's Http module?
Yes. The generated decoder works directly with Elm's Http.get, Http.post, and Http.request. Pass it to Http.expectJson: Http.get { url = 'https://api.example.com/users/1', expect = Http.expectJson GotUser userDecoder }. The Http module applies the decoder to the response body and delivers the result to your update function as a Msg containing Result Http.Error User. Http.Error covers both network failures and JSON decode failures, so a single case expression in your update function handles all failure scenarios.
How do I handle union types (custom types) from JSON?
The tool generates type aliases (record types) from JSON objects. If your API uses a discriminated union pattern — a JSON field that indicates which variant of a type the object represents, like a type field with values 'admin' or 'user' — the generated code will represent it as a String field. To properly model this as an Elm custom type, you need to write a custom decoder: Decode.field 'type' Decode.string |> Decode.andThen (\typeStr -> case typeStr of 'admin' -> Decode.succeed Admin 'user' -> Decode.succeed RegularUser _ -> Decode.fail ('Unknown user type: ' ++ typeStr)). The andThen combinator is what enables this pattern in the elm/json decoder API.
How to Convert JSON to Dart Classes for Flutter – Complete In-Depth Guide (2026)
How to convert JSON to Dart classes for Flutter in 2026. In-depth guide covering Dart model best practices, null safety, immutable classes, code generation with json_serializable & freezed, Flutter integration with Riverpod, and real-world architecture tips from a Principal Software Engineer with 15+ years experience.
What is JSON? How to Format, Validate & Use It (Complete Guide 2026)
What is JSON? How to Format, Validate & Use It (Complete Guide 2026). In-depth explanation of JSON syntax, real-world use cases, formatting best practices, common mistakes, advantages, disadvantages, and expert tips from a Principal Software Engineer with 15+ years experience.
How to validate JSON online (step-by-step guide)
Invalid JSON can break your application. Follow this guide to quickly validate and fix your JSON data.
Recent Activity
No recent activity