Open-source project
google/json_serializable.dart avatar
google/json_serializable.dart

json_serializable: three packages, one of which must sit in runtime dependencies

Generates utilities to aid in serializing to/from JSON.

1,620 stars463 forksDartBSD-3-Clause

At a glance

What is it?
The core generator is a dev dependency and the annotation package is a runtime dependency, and checked_yaml goes into dependencies even though it only affects error messages. Those three placements are the design this repository encodes.
Who is it for?
Adopt json_serializable if you want JSON handling generated from annotations rather than hand-written, since the generator and the Dart Build System handle the boilerplate and the mono-repo layout makes versioning coherent across the three packages. Do not adopt it if you need runtime-flexible key mapping, because generated code fixes the field names at build time and a dynamic wire format will not fit it.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 7 days ago.
What is it written in?
Mainly Dart, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • google/json_serializable.dart1,620 ★ · +1
Star history
Repository2026-10-162026-11-07
google/json_serializable.dart1.6k1.6k

1 Stars in the last 22 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Three packages, three different dependency placements

The repository publishes three packages, and the README is explicit about where each one belongs in a pubspec. That placement is not incidental formatting, it is the architecture.

`json_serializable` is the core package providing the generators for JSON-specific tasks, and it goes into `dev_dependencies:`. It is build-time only: it runs, it writes Dart source files, and it is not needed at runtime.

`json_annotation` is the annotation package, described as having no dependencies, and it goes into `dependencies:`. This is the one your library code imports to put annotations on your classes, so it ships with your app.

`checked_yaml` goes into `dependencies:` as well, which is the placement worth pausing on. Its job is to generate more helpful exceptions when decoding YAML documents using `json_serializable` and `yaml`. Nothing about it changes what your program computes; it changes what a failure tells you.

So a runtime dependency exists purely to improve error text. The alternative would have been to keep error-message enrichment in the dev dependency, but then the diagnostic detail would only exist inside the generator and would have to be baked into the generated code, and the README's choice is to have it available at decode time.

If you are adding these by hand, this is the line to get wrong. Putting `checked_yaml` in `dev_dependencies` is the kind of mistake that compiles locally and produces worse errors only in production.

It is a Dart Build System builder, not a runtime library

The one-line description at the top of the README is that this repository provides Dart Build System builders for handling JSON. That single sentence determines how the tool behaves.

Code generation happens at build time. Your annotated classes are inputs; the generator is a builder registered with the build system; the output is a Dart source file that your project then compiles like any other code. The consequence is that field names, conversions, and the fromJson and toJson pair are decided when you build, not when you run.

That has a good half and a bad half. The good half is that the serialisation code is ordinary Dart that a reader can open and understand, with no reflection at runtime and no interpreter between your data and the wire format. The bad half is that it cannot adapt to a wire format that changes at runtime.

So if your API's field naming is stable, generation is a clear win. If you need to honour a server-supplied field mapping, or accept several wire shapes for the same class, generated code with fixed names is the wrong tool and hand-written conversion is the honest answer.

The repository also includes an `example/` directory described as showing how to set up and use `json_serializable` and `json_annotation`, with its own README, pubspec, and both a `dart_test.yaml` and a `mono_pkg.yaml` in the example's test setup. That example is the fastest way to see the intended wiring.

The mono-repo is what makes the three versions line up

The repository is a mono-repo containing the three package directories side by side: `json_serializable/`, `json_annotation/`, and `checked_yaml/`, plus `example/`, `shared_test/`, `_test_yaml/`, and `tool/`.

Two files at the root tell you how it is managed. `mono_repo.yaml` is the configuration for the mono-repo tooling, which is how a Dart mono-repo declares its packages and the shared tooling and test setup they all use. `pubspec.yaml` at the root is the workspace manifest.

`shared_test/` is the part that matters most in practice. The repository includes a `shared_test/` directory for shared tests. For a code generator whose output is consumed by a separate annotation package, shared tests are the mechanism that keeps the contract honest.

`_test_yaml/` is a directory prefixed with an underscore, which by Dart package convention is not part of the published surface. It sits alongside a root `analysis_options.yaml` for lint configuration and a `.markdownlint.yaml` for documentation linting, so the repository lints its own README files too.

The practical consequence for you as a user is versioning. The three packages version independently on pub.dev, and the recent releases show them moving together: `json_serializable v6.14.0` on 2026-05-15 and `json_annotation v4.12.0` on 2026-05-15, published within minutes of it on the same day.

That coordination is what the mono-repo buys. When a generator changes its output, the annotation package it depends on is updated in the same commit rather than weeks later.

Release cadence and what the tags tell you

The recent releases are dated and consistent. `json_serializable v6.14.1` on 2026-07-30, `json_serializable v6.14.0` on 2026-05-15, and `json_annotation v4.12.0` on 2026-05-15.

So json_serializable is on a 6.x line and json_annotation is on a 4.x line, which is worth noting because the two have separate major version histories despite living in one repository and being used together. That is a normal outcome of semver across independently published packages, and it is the reason a pubspec will pin one to a 6.x constraint and the other to a 4.x constraint.

The repository is not archived, and the last push was on 2026-10-16, roughly two and a half months after the most recent release. So the source is moving while the published version is a little behind, which is normal for a generator that wants to land changes and cut a release later.

The licence is BSD-3-Clause, in the `LICENSE` file at the root.

Continuous integration includes a Dart CI workflow, referenced by the badge at the top of the README. Shared tests can help give you confidence that a change in one package does not break another.

Where this sits against the alternatives

The realistic comparison is with hand-written `fromJson` and `toJson`.

Hand-written serialisation is completely explicit. You can see every conversion, every default, and every null check, and you can edit it when the wire format is awkward. The cost is that it is a function you write, review, and keep in sync per class, and for a project with many model classes it is many chances to introduce a typo in a field name.

A runtime reflection library such as a mapper with annotations reads the class at runtime. That means no build step, which is a genuine advantage when you want to try something quickly, and a disadvantage when you want to see what the serialiser will actually do before shipping it. It also tends to be slower and less precise about types than generated code.

Generated code sits in between. You write annotations, the tool writes the conversion, and the generated file is readable code you can open when something looks wrong. The trade is build time and the loss of runtime flexibility.

Where checked_yaml fits into that comparison is worth separating out, because it is not an alternative to anything. It is an improvement to the failure path of the `yaml` package's decoding, made possible by the generated code having a fixed structure to attach better errors to. A hand-written serialiser does not have that opportunity, which is a small argument for the generated route if you use YAML configuration files as well as JSON.

Editorial conclusion

Adopt json_serializable if you want JSON handling generated from annotations rather than hand-written, since the generator and the Dart Build System handle the boilerplate and the mono-repo layout makes versioning coherent across the three packages. Do not adopt it if you need runtime-flexible key mapping, because generated code fixes the field names at build time and a dynamic wire format will not fit it. Verify first that checked_yaml is in your dependencies rather than dev_dependencies, since the README puts it there for error message quality.

Frequently asked questions

Which pubspec section does json_serializable go in?

json_serializable goes in dev_dependencies because it is a build-time code generator. json_annotation goes in dependencies, since your code imports the annotations. The README also puts checked_yaml in dependencies, not dev_dependencies, so its improved decoding exceptions are available at runtime.

What does the checked_yaml package do?

It generates more helpful exceptions when decoding YAML documents using json_serializable and package:yaml. It changes error message quality rather than program behaviour, and the README places it in dependencies rather than dev_dependencies for that reason.

Is json_serializable still maintained?

The repository is not archived and the last push was on 2026-10-16. Recent releases include json_serializable v6.14.1 on 2026-07-30 and json_annotation v4.12.0 on 2026-05-15, so the source is moving while the published version trails slightly.

Official sources

  1. google/json_serializable.dart on GitHub
  2. License: BSD-3-Clause
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/google-json-serializable-dart.svg)](https://hysenlabs.com/projects/google-json-serializable-dart)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/google-json-serializable-dart.svg)](https://hysenlabs.com/projects/google-json-serializable-dart)

Was this useful?