{"id":13485890,"url":"https://github.com/jdereg/json-io","last_synced_at":"2026-04-20T00:08:46.843Z","repository":{"id":547603,"uuid":"12594924","full_name":"jdereg/json-io","owner":"jdereg","description":"Convert Java to JSON/TOON and back. Supports complex object graphs, cyclic references, and TOON format for 40-50% LLM token savings","archived":false,"fork":false,"pushed_at":"2026-03-31T00:28:39.000Z","size":11807,"stargazers_count":376,"open_issues_count":0,"forks_count":120,"subscribers_count":21,"default_branch":"master","last_synced_at":"2026-03-31T00:28:58.654Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jdereg.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2013-09-04T15:44:02.000Z","updated_at":"2026-03-31T00:28:43.000Z","dependencies_parsed_at":"2022-08-16T10:30:45.119Z","dependency_job_id":"b77573e4-b335-46f7-bac0-0b091732640c","html_url":"https://github.com/jdereg/json-io","commit_stats":{"total_commits":1662,"total_committers":37,"mean_commits":44.91891891891892,"dds":"0.20818291215403129","last_synced_commit":"73a4315113417a2d0106a3ef4adf5c39f6a39162"},"previous_names":[],"tags_count":191,"template":false,"template_full_name":null,"purl":"pkg:github/jdereg/json-io","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdereg%2Fjson-io","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdereg%2Fjson-io/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdereg%2Fjson-io/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdereg%2Fjson-io/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jdereg","download_url":"https://codeload.github.com/jdereg/json-io/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdereg%2Fjson-io/sbom","scorecard":{"id":447737,"data":{"date":"2025-08-11","repo":{"name":"github.com/jdereg/json-io","commit":"e7059b16d507d9aa076883fa8e23eb773e94b75a"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.9,"checks":[{"name":"Maintained","score":10,"reason":"30 commit(s) and 2 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/26 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":8,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'contents' permission set to 'read': .github/workflows/claude-code-review.yml:23","Info: jobLevel 'pull-requests' permission set to 'read': .github/workflows/claude-code-review.yml:24","Info: jobLevel 'issues' permission set to 'read': .github/workflows/claude-code-review.yml:25","Info: jobLevel 'actions' permission set to 'read': .github/workflows/claude.yml:26","Info: jobLevel 'contents' permission set to 'read': .github/workflows/claude.yml:22","Info: jobLevel 'pull-requests' permission set to 'read': .github/workflows/claude.yml:23","Info: jobLevel 'issues' permission set to 'read': .github/workflows/claude.yml:24","Info: jobLevel 'contents' permission set to 'read': .github/workflows/gradle-publish.yml:19","Warn: jobLevel 'packages' permission set to 'write': .github/workflows/gradle-publish.yml:20","Warn: no topLevel permission defined: .github/workflows/claude-code-review.yml:1","Warn: no topLevel permission defined: .github/workflows/claude.yml:1","Warn: no topLevel permission defined: .github/workflows/gradle-publish.yml:1"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":4,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Warn: no linked content found","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Pinned-Dependencies","score":4,"reason":"dependency not pinned by hash detected -- score normalized to 4","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/claude-code-review.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/jdereg/json-io/claude-code-review.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/claude-code-review.yml:36: update your workflow using https://app.stepsecurity.io/secureworkflow/jdereg/json-io/claude-code-review.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/claude.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/jdereg/json-io/claude.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/claude.yml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/jdereg/json-io/claude.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/gradle-publish.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/jdereg/json-io/gradle-publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/gradle-publish.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/jdereg/json-io/gradle-publish.yml/master?enable=pin","Info:   0 out of   4 GitHub-owned GitHubAction dependencies pinned","Info:   2 out of   4 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":3,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'master'","Info: 'force pushes' disabled on branch 'master'","Warn: 'branch protection settings apply to administrators' is disabled on branch 'master'","Warn: could not determine whether codeowners review is allowed","Warn: no status checks found to merge onto branch 'master'","Warn: PRs are not required to make changes on branch 'master'; or we don't have data to detect it.If you think it might be the latter, make sure to run Scorecard with a PAT or use Repo Rules (that are always public) instead of Branch Protection settings"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 6 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-19T07:19:34.589Z","repository_id":547603,"created_at":"2025-08-19T07:19:34.590Z","updated_at":"2025-08-19T07:19:34.590Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31314284,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2024-07-31T18:00:33.511Z","updated_at":"2026-04-20T00:08:46.826Z","avatar_url":"https://github.com/jdereg.png","language":"Java","funding_links":[],"categories":["Groovy","项目","Projects","JSON","Code \u0026 Examples"],"sub_categories":["JSON","Development Tools"],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"infographic.jpeg\" alt=\"json-io infographic - JSON5, TOON, and Core Capabilities\" width=\"100%\" /\u003e\n\u003c/p\u003e\n\u003cp align=\"right\"\u003e\u003csub\u003eInfographic by \u003ca href=\"https://github.com/glaforge\"\u003eGuillaume Laforge\u003c/a\u003e\u003c/sub\u003e\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003cp\u003e\n    \u003ca href=\"https://central.sonatype.com/search?q=json-io\u0026namespace=com.cedarsoftware\"\u003e\n      \u003cimg src=\"https://badgen.net/maven/v/maven-central/com.cedarsoftware/json-io\" alt=\"Maven Central\" height=\"20\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"http://www.javadoc.io/doc/com.cedarsoftware/json-io\"\u003e\n      \u003cimg src=\"https://javadoc.io/badge/com.cedarsoftware/json-io.svg\" alt=\"Javadoc\" height=\"20\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/jdereg/json-io/blob/master/LICENSE\"\u003e\n      \u003cimg src=\"https://img.shields.io/badge/License-Apache%202.0-blue.svg\" alt=\"License\" height=\"20\" /\u003e\n    \u003c/a\u003e\n    \u003cimg src=\"https://img.shields.io/badge/JDK-8%20to%2024-orange\" alt=\"JDK 8–24\" height=\"20\" /\u003e\n    \u003ca href=\"https://json5.org/\"\u003e\n      \u003cimg src=\"https://img.shields.io/badge/JSON5-Full%20Support-brightgreen\" alt=\"JSON5\" height=\"20\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://toonformat.dev/\"\u003e\n      \u003cimg src=\"https://img.shields.io/badge/TOON-Read%2FWrite-blueviolet\" alt=\"TOON\" height=\"20\" /\u003e\n    \u003c/a\u003e\n  \u003c/p\u003e\n\n  \u003cp\u003e\n    \u003ca href=\"https://github.com/jdereg/json-io\"\u003e\n      \u003cimg src=\"https://img.shields.io/github/stars/jdereg/json-io?style=social\" alt=\"GitHub stars\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/jdereg/json-io/fork\"\u003e\n      \u003cimg src=\"https://img.shields.io/github/forks/jdereg/json-io?style=social\" alt=\"GitHub forks\" /\u003e\n    \u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\nLLM applications waste 40-50% of their token budget on JSON syntax overhead — braces, brackets, quotes, and commas that carry zero semantic information. **json-io** is a Java serialization library that reads and writes **JSON**, **JSON5**, and **[TOON](https://toonformat.dev/)** (Token-Oriented Object Notation) — a format that strips that overhead while preserving full data fidelity. It also handles what Jackson/Gson cannot: cyclic object graphs, automatic polymorphic types, and zero-config serialization of 60+ built-in Java types.\n\nFeatured on [json.org](http://json.org) and [Baeldung](https://www.baeldung.com/java-json-toon-format-libraries). See the [interactive JSON vs TOON comparison](https://jdereg.github.io/json-io/compare/).\n\n## Quick Start\n\n```java\n// JSON\nString json = JsonIo.toJson(myObject);\nMyClass obj = JsonIo.toJava(json).asClass(MyClass.class);\n\n// JSON5\nString json5 = JsonIo.toJson(myObject, new WriteOptionsBuilder().json5().build());\n\n// TOON (~40-50% fewer tokens than JSON)\nString toon = JsonIo.toToon(myObject);\nMyClass obj = JsonIo.fromToon(toon).asClass(MyClass.class);\n\n// Standard JSON (Jackson-compatible output — no @type, no @id/@ref, stringified map keys)\nString json = JsonIo.toJson(myObject, new WriteOptionsBuilder().standardJson().build());\n```\n\n## Installation\n\n**Gradle**\n```groovy\nimplementation 'com.cedarsoftware:json-io:4.101.0'\n```\n\n**Maven**\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.cedarsoftware\u003c/groupId\u003e\n  \u003cartifactId\u003ejson-io\u003c/artifactId\u003e\n  \u003cversion\u003e4.101.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nLatest version: [![Maven Central](https://img.shields.io/maven-central/v/com.cedarsoftware/json-io)](https://central.sonatype.com/artifact/com.cedarsoftware/json-io)\n\n---\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong style=\"font-size:1.4em\"\u003eJSON\u003c/strong\u003e\u003c/summary\u003e\n\n### Usage\n\n```java\n// Write JSON\nString json = JsonIo.toJson(myObject);\nJsonIo.toJson(outputStream, myObject, writeOptions);\n\n// Read JSON to typed Java objects\nEmployee emp = JsonIo.toJava(json).asClass(Employee.class);\nEmployee emp = JsonIo.toJava(inputStream, readOptions).asClass(Employee.class);\n\n// Read JSON to Maps (no classes needed)\nMap map = JsonIo.toMaps(json).asMap();\n\n// Generic types\nList\u003cEmployee\u003e list = JsonIo.toJava(json).asType(new TypeHolder\u003cList\u003cEmployee\u003e\u003e(){});\n```\n\n### Standard JSON Mode — Jackson Compatible\n\n**One flag flips json-io's output to match Jackson.** Use `standardJson()` to produce output\nbyte-compatible with what Jackson (with `JavaTimeModule` and the Spring Boot default of\n`WRITE_DATES_AS_TIMESTAMPS=false`) produces:\n\n```java\nWriteOptions opts = new WriteOptionsBuilder()\n        .standardJson()    // will be the default in 5.0.0 — this call becomes optional\n        .build();\nString json = JsonIo.toJson(myObject, opts);\n```\n\nThis configures: `showTypeInfoNever`, `showRootTypeInfo(false)`, `cycleSupport(false)`,\n`stringifyMapKeys(true)`, `writeOptionalAsObject(false)`, `preserveLeafContainerIdentity(false)`,\n`isoDateFormat()` (ISO-8601 dates for `java.util.Date` — `java.time.*` are already ISO-8601),\nand `useMetaPrefixDollar()`.\n\n**Use json-io anywhere you'd use Jackson** for standard JSON output, and get the full json-io\nfeature set whenever you need it: cyclic graph preservation, polymorphic `@type` auto-detection,\nand first-class **JSON5** + **TOON** output — all from the same builder.\n\n**Need Jackson-style output *plus* graph fidelity?** If your data has shared references or cycles\nand you want them preserved (something Jackson only does with `@JsonIdentityInfo` annotated on\nevery affected class), turn cycle support back on after `standardJson()`:\n\n```java\nWriteOptions opts = new WriteOptionsBuilder()\n        .standardJson()\n        .cycleSupport(true)    // Jackson-compatible output, but $id/$ref are emitted when shared refs exist\n        .build();\n```\n\nYou get Jackson-compatible field names, ISO-8601 dates, and stringified Map keys — **plus** json-io's\nautomatic shared-reference and cycle preservation. No class annotations required.\n\n### json-io vs Jackson vs Gson\n\n**Object graph handling**\n\n| Capability | json-io | Jackson | Gson |\n|------------|---------|---------|------|\n| Cyclic object graphs | Automatic (`$id`/`$ref`) -or- `JsonIoException` with `cycleSupport(false)` | Requires `@JsonIdentityInfo` | `StackOverflowError` |\n| Shared object references | Preserved (`$id`/`$ref`) -or- duplicated with `cycleSupport(false)` | Requires `@JsonIdentityInfo` | Duplicated (no identity) |\n| Polymorphic types | Automatic -or- use `@IoTypeInfo`/`@JsonTypeInfo` | Requires `@JsonTypeInfo` | Requires `TypeAdapter` |\n| Unknown `$type` values | Graceful fallback to `Map` | Exception | Exception |\n\n**Map handling**\n\n| Capability | json-io | Jackson | Gson |\n|------------|---------|---------|------|\n| `Map\u003cString, V\u003e` | Standard JSON object | Same | Same |\n| `Map\u003cLong, V\u003e`, `Map\u003cUUID, V\u003e` | `stringifyMapKeys` → `{\"100\": v}` | `toString()` (fragile) | `enableComplexMapKeySerialization()` |\n| `Map\u003cPOJO, V\u003e` (complex keys) | Full fidelity via `$keys`/`$items` | `toString()` (lossy) | Array of key-value pairs |\n\n**Format \u0026 configuration**\n\n| Capability | json-io | Jackson | Gson |\n|------------|---------|---------|------|\n| Standard JSON output | `.standardJson()` — Jackson-compatible | Default | Default |\n| JSON5 support | Full read/write (native) | Partial read only | None |\n| TOON support | Full read/write (40-50% fewer tokens) | None | None |\n| Configuration | Zero-config; optional `@Io*` | Annotation-heavy (`@Json*`) | Annotations + builders |\n| Jackson annotations | Recognized reflectively | Native | Not supported |\n| Two parse modes | `toJava()` (typed) + `toMaps()` | Typed only | Typed only |\n\n**Runtime**\n\n| Capability | json-io | Jackson | Gson |\n|------------|---------|---------|------|\n| Performance (simple DTOs) | 1.3–2.0x vs Jackson (all paths under 2x) | Fastest | ~1.3x vs Jackson |\n| Dependencies | java-util only (~1MB) | Multiple JARs (~2.5MB+) | Single JAR (~300KB) |\n| Java version | JDK 8+ | JDK 8+ | JDK 8+ |\n\n**On performance:** Jackson is faster for simple DTOs, but json-io stays **under 2x Jackson on every read/write mode** on the `JsonPerformanceTest` benchmark (100,000 iterations, diverse POJO workload — nested collections, floats, `BigDecimal`, `java.time.*`, UUIDs, nullable fields). In real-world applications, serialization is typically \u003c1% of total request time — the rest is network I/O, database queries, and business logic. json-io's additional capabilities (cycles, polymorphism, zero-config, JSON5, TOON) often matter more than raw serialization throughput.\n\n\u003cdetails\u003e\n\u003csummary\u003eMeasured ratios vs Jackson (lower is faster; 1.0 = Jackson parity)\u003c/summary\u003e\n\n| Mode | JsonIo | TOON |\n|---|---|---|\n| Read `toJava` (typed) | 1.92x | 1.97x |\n| Read `toMaps` (class-independent) | 1.32x | 1.73x |\n| Write `cycleSupport=true` (default) | 1.75x | 1.78x |\n| Write `cycleSupport=false` (DTOs/acyclic) | 1.60x | 1.66x |\n| Write `toMaps` `cycleSupport=true` | 1.83x | 1.84x |\n| Write `toMaps` `cycleSupport=false` | 1.57x | 1.68x |\n\nMeasured on JDK 21, `json-io 4.101.0` vs `jackson-databind 2.21.2`. Reproduce with `mvn -q -pl json-io -DskipTests test-compile exec:java -Dexec.classpathScope=test -Dexec.mainClass=com.cedarsoftware.io.JsonPerformanceTest` (100k iterations after 10k warmup; expect ±3% run-to-run noise from thermal / GC). Jackson is configured with `JavaTimeModule` and `WRITE_DATES_AS_TIMESTAMPS=false` to match what Spring Boot emits by default.\n\n\u003c/details\u003e\n\n**Performance tip:** Use `cycleSupport(false)` for ~35-40% faster writes when your data is acyclic (DTOs, POJOs, tree-shaped data).\n\n### Key Features\n\n- **Jackson-compatible standard JSON** — `writeOptions.standardJson()` matches Spring Boot's default Jackson output (ISO-8601 dates, stringified Map keys, no proprietary metadata). Drop-in for Jackson.\n- Two modes: typed Java objects (`toJava()`) or class-independent Maps (`toMaps()`)\n- Preserves object references and handles cyclic relationships via `$id`/`$ref` — zero annotations required (Jackson needs `@JsonIdentityInfo` on every class)\n- Supports polymorphic types and complex object graphs\n- Zero external dependencies (other than java-util)\n- Stringify-able map keys: `Map\u003cLong, V\u003e` writes `{\"100\": value}` with `stringifyMapKeys(true)`\n- Extensive configuration via `ReadOptionsBuilder` and `WriteOptionsBuilder`\n- Parse JSON with unknown `$type` references into a Map-of-Maps without requiring classes on classpath\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong style=\"font-size:1.4em\"\u003eJSON5\u003c/strong\u003e\u003c/summary\u003e\n\n[JSON5](https://json5.org/) is an extension to JSON that makes it more human-friendly. json-io provides **complete JSON5 support** for both reading and writing — the only major Java JSON library to do so natively.\n\n### Reading JSON5\n\njson-io accepts all JSON5 extensions by default — no configuration needed:\n\n```java\nString json5 = \"{ name: 'John', age: 30, /* comment */ }\";\nPerson p = JsonIo.toJava(json5).asClass(Person.class);\n```\n\nSupported: single-line (`//`) and multi-line (`/* */`) comments, single-quoted strings, unquoted keys, trailing commas, hex integers, `Infinity`/`NaN`/`-Infinity`, and more.\n\n### Writing JSON5\n\n```java\nWriteOptions opts = new WriteOptionsBuilder().json5().build();\nString json5 = JsonIo.toJson(myObject, opts);\n```\n\nThe `json5()` umbrella enables:\n- **Unquoted keys** — object keys that are valid identifiers are written without quotes\n- **Smart quotes** — strings containing `\"` (but not `'`) use single quotes\n- **Infinity/NaN literals** — special float/double values as literals instead of `null`\n- **Stringify map keys** — `Map\u003cLong, V\u003e` writes `{100: value}` instead of `$keys`/`$items`\n- **No type info** — `showTypeInfoNever()` + `cycleSupport(false)` for clean output\n\nIndividual features can be enabled separately. See the [User Guide](/user-guide.md#json5-support) for details.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong style=\"font-size:1.4em\"\u003eTOON\u003c/strong\u003e\u003c/summary\u003e\n\n[TOON](https://toonformat.dev/) (Token-Oriented Object Notation) is an indentation-based format that produces **~40-50% fewer tokens** than JSON — ideal for LLM applications where token count directly impacts cost and context window usage.\n\n- **No braces, brackets, or commas** — structure is expressed through indentation\n- **No quoting** for most keys and values — quotes only when needed\n- **Compact arrays** — inline `[N]: a,b,c` or list format with `- ` prefixed elements\n- **Tabular format** — arrays of uniform objects as CSV-like rows with column headers\n- **Key folding** — nested keys like `address.city: Denver` flatten one level of nesting\n- **Full fidelity** — most data requires no extra metadata at all\n\n**JSON:**\n```json\n{\"team\":\"Rockets\",\"players\":[{\"name\":\"John\",\"age\":30,\"position\":\"guard\"},{\"name\":\"Sue\",\"age\":27,\"position\":\"forward\"},{\"name\":\"Mike\",\"age\":32,\"position\":\"center\"}]}\n```\n\n**TOON (same data, ~45% fewer tokens):**\n```yaml\nteam: Rockets\nplayers:\n  name, age, position\n  John, 30, guard\n  Sue, 27, forward\n  Mike, 32, center\n```\n\n### Usage\n\n```java\n// Write TOON\nString toon = JsonIo.toToon(myObject);\n\n// Read TOON back to typed Java object\nPerson p = JsonIo.fromToon(toon).asClass(Person.class);\n\n// Read TOON to Maps (no class needed)\nMap map = JsonIo.fromToon(toon).asMap();\n```\n\nRequest TOON format for LLM applications: `Accept: application/vnd.toon`\n\nSee the [Baeldung tutorial](https://www.baeldung.com/java-json-toon-format-libraries) for a walkthrough of JSON, JSON5, and TOON serialization with json-io, and the [interactive JSON vs TOON comparison](https://jdereg.github.io/json-io/compare/).\n\n### vs JToon\n\n| Capability | json-io | JToon |\n|---|---|---|\n| Built-in types | 60+ | ~15 |\n| Map key types | Any serializable type | Strings only |\n| EnumSet support | Yes | No |\n| Full Java serialization | Yes — any object graph | Limited to supported types |\n| Cycle support (`$id`/`$ref`) | Yes (opt-in) | No |\n| Annotation support | `@Io*` + Jackson (reflective) | None |\n| Dependencies | java-util only | Jackson |\n| Status | Stable, production-ready | Beta (v1.x.x) |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong style=\"font-size:1.4em\"\u003eSpring Boot Integration\u003c/strong\u003e\u003c/summary\u003e\n\njson-io provides a Spring Boot starter for seamless integration with Spring MVC and WebFlux applications.\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.cedarsoftware\u003c/groupId\u003e\n  \u003cartifactId\u003ejson-io-spring-boot-starter\u003c/artifactId\u003e\n  \u003cversion\u003e4.101.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nYour REST controllers now support JSON, JSON5, and TOON formats via content negotiation:\n\n```java\n@RestController\npublic class ApiController {\n    @GetMapping(\"/data\")\n    public MyData getData() {\n        return myData;  // Returns JSON, JSON5, or TOON based on Accept header\n    }\n}\n```\n\n### Spring AI Integration\n\njson-io provides a Spring AI module that reduces LLM token usage by ~40-50% using TOON format for tool call results and structured output parsing.\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.cedarsoftware\u003c/groupId\u003e\n  \u003cartifactId\u003ejson-io-spring-ai-toon\u003c/artifactId\u003e\n  \u003cversion\u003e4.101.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nAuto-configured: tool call results are serialized to TOON automatically. For structured output, use `ToonBeanOutputConverter\u003cT\u003e`:\n\n```java\nToonBeanOutputConverter\u003cPerson\u003e converter = new ToonBeanOutputConverter\u003c\u003e(Person.class);\nPerson person = chatClient.prompt()\n    .user(\"Get info about John\")\n    .call()\n    .entity(converter);\n```\n\n**Also supports WebFlux and WebClient** for reactive applications.\n\nSee the [Spring Integration Guide](/user-guide-spring.md) for configuration options, WebFlux usage, customizers, and Jackson coexistence modes.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong style=\"font-size:1.4em\"\u003eAnnotations, Types \u0026amp; Configuration\u003c/strong\u003e\u003c/summary\u003e\n\n### Annotation Support\n\njson-io provides 25 annotations in the `com.cedarsoftware.io.annotation` package for controlling serialization and deserialization:\n\n| Annotation | Target | Purpose |\n|---|---|---|\n| `@IoProperty(\"name\")` | Field | Rename field in JSON |\n| `@IoIgnore` | Field | Exclude field |\n| `@IoIgnoreProperties({\"a\",\"b\"})` | Class | Exclude fields by name |\n| `@IoAlias({\"alt1\",\"alt2\"})` | Field | Accept alternate names on read |\n| `@IoPropertyOrder({\"x\",\"y\"})` | Class | Control field order on write |\n| `@IoInclude(Include.NON_NULL)` | Field | Skip null on write |\n| `@IoCreator` | Constructor/Method | Custom deserialization constructor or static factory |\n| `@IoValue` | Method | Single-value serialization |\n| `@IoNaming(Strategy.SNAKE_CASE)` | Class | Naming strategy for all fields |\n| `@IoIncludeProperties({\"a\",\"b\"})` | Class | Whitelist of included fields |\n| `@IoIgnoreType` | Class | Exclude all fields of this type everywhere |\n| `@IoTypeInfo(LinkedList.class)` | Field | Default concrete type when `$type` absent; also eliminates `$type` on write when runtime type matches |\n| `@IoDeserialize(as=LinkedList.class)` | Field/Class | Force type override during deserialization; also eliminates `$type` on write when runtime type matches |\n| `@IoClassFactory(MyFactory.class)` | Class | Specify a ClassFactory for deserialization |\n| `@IoGetter(\"fieldName\")` | Method | Custom getter method for serialization |\n| `@IoSetter(\"fieldName\")` | Method | Custom setter method for deserialization |\n| `@IoNonReferenceable` | Class | Suppress `$id`/`$ref` for instances of this type |\n| `@IoNotCustomReader` | Class | Suppress custom reader (use standard deserialization) |\n| `@IoNotCustomWritten` | Class | Suppress custom writer (use standard serialization) |\n| `@IoCustomWriter(MyWriter.class)` | Class | Specify custom `JsonClassWriter` for serialization |\n| `@IoCustomReader(MyReader.class)` | Class | Specify custom `JsonClassReader` for deserialization |\n| `@IoTypeName(\"ShortName\")` | Class | Alias for `$type` in JSON (replaces FQCN) |\n| `@IoAnySetter` | Method | Receive unrecognized JSON fields during deserialization |\n| `@IoAnyGetter` | Method | Provide extra fields during serialization |\n| `@IoFormat(\"pattern\")` | Field | Per-field format pattern (`String.format`, `DecimalFormat`, `DateTimeFormatter`, or `SimpleDateFormat`) |\n\nAdditionally, json-io **reflectively honors Jackson annotations** when they are on the classpath — with zero compile-time dependency on Jackson. Supported: `@JsonProperty`, `@JsonIgnore`, `@JsonIgnoreProperties`, `@JsonAlias`, `@JsonPropertyOrder`, `@JsonInclude`, `@JsonCreator`, `@JsonValue`, `@JsonIgnoreType`, `@JsonTypeInfo`, `@JsonIncludeProperties`, `@JsonNaming`, `@JsonDeserialize`, `@JsonGetter`, `@JsonSetter`, `@JsonTypeName`, `@JsonFormat`, `@JsonAnySetter`, `@JsonAnyGetter`.\n\n**Precedence:** Programmatic API \u003e json-io annotations \u003e Jackson annotations.\n\nSee the [Annotations section of the User Guide](/user-guide.md#annotations) for full details and examples.\n\n### Supported Types (60+ built-in)\n\njson-io handles your **business objects, DTOs, and Records** automatically—no annotations required. It also provides optimized handling for these built-in types:\n\n| Category | Types |\n|----------|-------|\n| Primitives | `byte`, `short`, `int`, `long`, `float`, `double`, `boolean`, `char` + wrappers |\n| Numbers | `BigInteger`, `BigDecimal`, `AtomicInteger`, `AtomicLong`, `AtomicBoolean` |\n| Date/Time | `Date`, `Calendar`, `Instant`, `LocalDate`, `LocalTime`, `LocalDateTime`, `ZonedDateTime`, `OffsetDateTime`, `OffsetTime`, `Duration`, `Period`, `Year`, `YearMonth`, `MonthDay`, `TimeZone`, `ZoneId`, `ZoneOffset`, `java.sql.Date`, `Timestamp` |\n| Strings | `String`, `StringBuffer`, `StringBuilder`, `char[]`, `CharBuffer` |\n| Binary | `byte[]`, `ByteBuffer`, `BitSet` |\n| IDs | `UUID`, `URI`, `URL`, `Class`, `Locale`, `Currency`, `Pattern`, `File`, `Path` |\n| Geometric | `Color`, `Dimension`, `Point`, `Rectangle`, `Insets` |\n| Other | `Enum` (any), `Throwable`, all `Collection`, `Map`, `EnumSet`, and array types |\n\nSee the [complete type comparison](/user-guide.md#toon-supported-types) showing json-io's comprehensive support vs other TOON implementations.\n\n### Key Features\n\n- Fully compatible with both JPMS and OSGi environments\n- Zero external dependencies (other than java-util)\n- Lightweight (`json-io.jar` is ~330K, `java-util` is ~700K)\n- Compatible with JDK 1.8 through JDK 24\n- The library is built with the `-parameters` compiler flag. Parameter names are now retained for tasks such as constructor discovery.\n- Optional unsafe mode for deserializing package-private classes, inner classes, and classes without accessible constructors (opt-in for security)\n- Extensive configuration options via `ReadOptionsBuilder` and `WriteOptionsBuilder`\n\n\u003c/details\u003e\n\n## Documentation\n\n- [User Guide](/user-guide.md)\n- [WriteOptions Reference](/user-guide-writeOptions.md)\n- [ReadOptions Reference](/user-guide-readOptions.md)\n- [Spring Integration Guide](/user-guide-spring.md)\n- [Revision History](/changelog.md)\n\n**Articles \u0026 Tutorials**\n- [JSON, TOON, and Java Format Libraries](https://www.baeldung.com/java-json-toon-format-libraries) — Baeldung tutorial covering JSON, JSON5, and TOON serialization with json-io\n\n## Release [![Maven Central](https://img.shields.io/maven-central/v/com.cedarsoftware/json-io)](https://central.sonatype.com/artifact/com.cedarsoftware/json-io)\n\n| | |\n|---|---|\n| **Bundling** | JPMS \u0026 OSGi |\n| **Java** | JDK 1.8+ (multi-release JAR with module-info.class) |\n| **Package** | com.cedarsoftware.io |\n\n**API** — Static methods on [JsonIo](/json-io/src/main/java/com/cedarsoftware/io/JsonIo.java): `toJson()`, `toJava()`, `toMaps()`, `toToon()`, `fromToon()`, `formatJson()`, `deepCopy()`\n\nConfigure via [ReadOptionsBuilder](/user-guide-readOptions.md) and [WriteOptionsBuilder](/user-guide-writeOptions.md). Use [ClassFactory](/json-io/src/main/java/com/cedarsoftware/io/ClassFactory.java) for difficult-to-instantiate classes.\n\n### Logging\n\njson-io uses `java.util.logging` to minimize dependencies. See the [user guide](/user-guide.md#redirecting-javautillogging) to route logs to SLF4J or Log4j 2.\n\n---\n\nFor useful Java utilities, check out [java-util](http://github.com/jdereg/java-util)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdereg%2Fjson-io","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjdereg%2Fjson-io","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdereg%2Fjson-io/lists"}