json-iterator/go
A high-performance 100% compatible drop-in replacement of "encoding/json"
Healthy across all four use cases
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓31+ active contributors
- ✓Distributed ownership (top contributor 37% of recent commits)
- ✓MIT licensed
Show 3 more →Show less
- ✓CI configured
- ✓Tests present
- ⚠Stale — last commit 2y ago
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/json-iterator/go)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/json-iterator/go on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: json-iterator/go
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/json-iterator/go shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- 31+ active contributors
- Distributed ownership (top contributor 37% of recent commits)
- MIT licensed
- CI configured
- Tests present
- ⚠ Stale — last commit 2y ago
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live json-iterator/go
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/json-iterator/go.
What it runs against: a local clone of json-iterator/go — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in json-iterator/go | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 742 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of json-iterator/go. If you don't
# have one yet, run these first:
#
# git clone https://github.com/json-iterator/go.git
# cd go
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of json-iterator/go and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "json-iterator/go(\\.git)?\\b" \\
&& ok "origin remote is json-iterator/go" \\
|| miss "origin remote is not json-iterator/go (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "jsoniter.go" \\
&& ok "jsoniter.go" \\
|| miss "missing critical file: jsoniter.go"
test -f "config.go" \\
&& ok "config.go" \\
|| miss "missing critical file: config.go"
test -f "iter.go" \\
&& ok "iter.go" \\
|| miss "missing critical file: iter.go"
test -f "adapter.go" \\
&& ok "adapter.go" \\
|| miss "missing critical file: adapter.go"
test -f "any.go" \\
&& ok "any.go" \\
|| miss "missing critical file: any.go"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 742 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~712d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/json-iterator/go"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
json-iterator/go is a high-performance drop-in replacement for Go's standard library encoding/json package that achieves 4-6x faster decoding and 2-3x faster encoding while maintaining 100% API compatibility. It uses aggressive optimization techniques like streaming parsing, reflection caching, and minimal allocations to outperform the standard library without requiring code changes. Modular architecture where any.go and associated any_*.go files (any_array.go, any_object.go, any_int64.go, etc.) implement a polymorphic type system for dynamic JSON values; adapter.go bridges to encoding/json API; config.go manages multiple Config instances for different compatibility levels (ConfigCompatibleWithStandardLibrary, ConfigFastest); extension_tests/ and extra/ (binary_as_string_codec.go, fuzzy_decoder.go) show extensibility patterns; benchmarks/ isolate performance testing.
👥Who it's for
Go backend engineers and microservice developers who need to parse or serialize large volumes of JSON data (APIs, message queues, log processing) and want dramatic performance gains without rewriting existing json.Unmarshal/json.Marshal call sites.
🌱Maturity & risk
Production-ready and actively maintained. The project has comprehensive test coverage across api_tests/, any_tests/, extension_tests/, and benchmarks/ directories, uses Travis CI for continuous integration, maintains codecov tracking, and supports Go 1.12+. The codebase is stable with clear semantic versioning via Gopkg.lock, though commit recency should be verified.
Low risk for standard use cases. Dependency footprint is minimal (modern-go/concurrent, modern-go/reflect2, google/gofuzz for testing). The main risk is single-maintainer dependency on taowen@gmail.com listed in README, and the project's compatibility claims require thorough testing in your specific workload since edge cases in stdlib behavior vary.
Active areas of work
The repository appears to be in maintenance mode rather than active feature development. No specific recent commits or open PRs are visible in the file listing. Focus areas are likely bug fixes and compatibility with newer Go versions (evidenced by encoder_18_test.go for Go 1.8+ features). The extra/ directory suggests custom codecs (binary_as_string_codec, time_as_int64_codec) are being added for specialized use cases.
🚀Get running
git clone https://github.com/json-iterator/go.git
cd go
go mod download
go test ./...
Daily commands:
go test ./api_tests -v # API compatibility tests
go test ./benchmarks -bench=. -benchmem # Performance benchmarks
go test ./any_tests -v # Dynamic type tests
go test ./extension_tests -v # Plugin/codec tests
🗺️Map of the codebase
jsoniter.go— Main entry point exposing the public API that serves as a drop-in replacement for encoding/json; defines Marshal, Unmarshal, and core configurationconfig.go— Central configuration system that controls codec behavior, extension registration, and feature toggles; essential for understanding customization pointsiter.go— Core iterator abstraction for streaming JSON deserialization; handles reading and parsing logic that underlies all decoding operationsadapter.go— Bridges jsoniter with encoding/json interfaces; critical for maintaining 100% compatibility and enabling drop-in replacementany.go— Dynamic type wrapper enabling generic JSON value access without pre-defined structs; foundational for flexible JSON handling patternsreflect.go— Reflection-based codec system dispatcher that routes encoding/decoding to type-specific handlers; core performance optimization layerstream.go— High-level streaming encoder API for writing JSON output incrementally; complements iter.go for symmetric encode/decode paths
🛠️How to make changes
Add a Custom Type Codec
- Create a new file in the main package (e.g., custom_type.go) and define your encoding/decoding logic with custom functions (
config.go) - Register the custom type in config using SetEncoderFunc(reflect.TypeOf(MyType{}), myEncoderFunc) and SetDecoderFunc(reflect.TypeOf(MyType{}), myDecoderFunc) (
config.go) - Test by calling json.NewConfig(), applying your codec registration, and using NewDecoder/NewEncoder from that config (
jsoniter.go)
Add a New Any Type Handler
- Create any_newtype.go following the pattern of any_int64.go, implementing the Any interface methods (Get, IndexArray, MapIndex, etc.) (
any.go) - Update the ParseAny function in any.go to instantiate your new type when appropriate (
any.go) - Add test file in any_tests/ directory with test cases for your new type's methods (
any_tests)
Add a New Iterator Parsing Method
- Add the parsing logic in iter.go or create a new iter_*.go file following the naming convention (e.g., iter_custom.go) (
iter.go) - Export a public method on Iterator struct (e.g., ReadCustom()) that consumes bytes and returns the parsed value (
iter.go) - Add tests in misc_tests/ or skip_tests/ with test cases covering normal, edge, and error conditions (
misc_tests)
Add a New Stream Encoding Method
- Add the encoding logic in stream.go or create stream_custom.go following the pattern of stream_str.go (
stream.go) - Export a public method on Stream struct (e.g., WriteCustom(value CustomType)) that buffers bytes and handles flushing (
stream.go) - Add benchmark and unit tests in benchmarks/ or api_tests/ directory (
benchmarks)
🔧Why these technologies
- Reflection-based codec generation (reflect.go, reflect_*.go) — Enables 100% compatibility with encoding/json while maintaining high performance through caching and specialized type handlers
- Iterator/streaming pattern (iter.go, stream.go) — Provides memory-efficient incremental parsing and serialization without materializing entire JSON structures
- Object pooling (pool.go) — Reduces garbage collection pressure by reusing Iterator and Stream objects across multiple unmarshal/marshal operations
- Dynamic value wrapper (any.go) — Enables flexible runtime value inspection without knowing types ahead of time, supporting REPL-style or dynamic JSON navigation
- Two-mode skip logic (iter_skip.go, iter_skip_strict.go, iter_skip_sloppy.go) — Allows both strict RFC 7159 compliance and lenient parsing for real-world malformed JSON through pluggable skip implementations
⚖️Trade-offs already made
-
Reflection-based type dispatch instead of code generation at compile time
- Why: Simplifies implementation and allows runtime configuration without build-time tools
- Consequence: Small startup cost for first-time encoding/decoding of a type, mitigated by aggressive caching; trades build complexity for runtime flexibility
-
undefined
- Why: undefined
- Consequence: undefined
🪤Traps & gotchas
Config objects are mutable singletons (ConfigCompatibleWithStandardLibrary is a package-level var)—modifying them affects all subsequent calls, which can cause subtle test interference if tests modify global config. The project relies on modern-go/reflect2 for reflection performance, so reflect2 API stability is a hidden dependency. Some optimizations assume specific Go runtime behavior (e.g., string interning patterns) which may differ across versions. Tests in any_tests/ and api_tests/ must be run separately; no unified test suite command is obvious from the structure.
🏗️Architecture
💡Concepts to learn
- Reflection caching with type handles — jsoniter avoids repeated reflection work by caching type metadata in modern-go/reflect2 handles—critical to understanding why it's 4-6x faster despite dynamic behavior
- Streaming/lazy evaluation — The Any interface pattern (any_array.go, any_object.go) defers full parsing until accessed—enabling efficient handling of massive JSON without materializing entire objects
- Polymorphic type dispatch without vtables — any.go's interface-based Any type with multiple implementations (any_int64.go, any_str.go, any_array.go) achieves Go's zero-cost abstraction—understanding the trade-offs vs. type switches is key to extending the library
- Memory pool allocation patterns — The Config system manages reader/writer pools and buffer reuse—seen in benchmarks showing 160 B/op vs. stdlib's 1960 B/op, critical for production latency-sensitive systems
- Codec plugin architecture — extra/ modules (binary_as_string_codec.go, fuzzy_decoder.go, time_as_int64_codec.go) register custom type handlers via config—enables domain-specific optimizations without forking the core library
- Unsafe pointer tricks for performance — Go's unsafe package likely used in modern-go/reflect2 integration for zero-copy parsing—hidden optimization you should be aware of when debugging crashes or memory safety issues
- Fuzzing-driven test generation — google/gofuzz dependency (in Gopkg.toml) suggests fuzz testing used to find edge cases in JSON parsing—important for understanding test coverage strategy and how to add fuzz tests for new features
🔗Related repos
mailru/easyjson— Direct competitor using code generation for compile-time JSON marshaling—referenced in README benchmarks as faster but requiring static generation, unlike jsoniter's dynamic approachjson-iterator/java— Same high-performance JSON library for Java—shows design patterns and performance techniques that inspired the Go version, useful for understanding architectural decisionsmodern-go/reflect2— Hard dependency providing faster reflection APIs—understanding reflect2's design is essential for optimizing any.go and config.go's type handlinggo-json-experiment/json— Experimental Go stdlib JSON package exploring future improvements—provides context for stdlib compatibility tradeoffs and potential breaking changes in Go 1.18+json-iterator/test-data— Companion repo likely containing test fixtures and corpus data for fuzzing and compatibility validation across encoding/json edge cases
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive test coverage for iter_skip.go strict vs sloppy mode edge cases
The repo has both iter_skip_strict.go and iter_skip_sloppy.go implementations but only iter_skip_sloppy_test.go exists. There's no test file for strict mode skipping, and no comparative tests verifying the behavioral differences between modes. This is critical for a JSON parser where correctness is paramount.
- [ ] Create iter_skip_strict_test.go with unit tests for strict mode JSON skipping (invalid UTF-8, control characters, etc.)
- [ ] Add comparative test cases in a new iter_skip_modes_test.go that verify strict vs sloppy behavior divergence
- [ ] Test edge cases: deeply nested structures, large numbers, escaped characters, and malformed JSON in both modes
- [ ] Verify test coverage reaches >90% for both iter_skip implementations
Add integration tests for extra/ codec extensions with standard library compatibility
The extra/ directory contains specialized codecs (binary_as_string, time_as_int64, fuzzy_decoder, etc.) but lacks integration tests verifying they work correctly with the main jsoniter API. Each codec has isolated tests, but no cross-codec tests or compatibility checks with custom struct marshaling.
- [ ] Create extra/integration_test.go with tests combining multiple codecs on complex nested structs
- [ ] Add tests verifying extra codecs don't break standard json.Marshaler/json.Unmarshaler interfaces
- [ ] Test time_as_int64_codec with fuzzy_decoder together to ensure interoperability
- [ ] Add benchmark comparison in benchmarks/ showing codec overhead (extra/time_as_int64_codec_bench_test.go)
Add GitHub Actions workflow replacing deprecated Travis CI for multi-version Go testing
The repo uses .travis.yml (deprecated) and go 1.12 is EOL. There's no modern CI workflow file. This is critical for a drop-in replacement library that must verify compatibility across Go versions (1.18+, 1.19, 1.20, etc.).
- [ ] Create .github/workflows/test.yml with matrix testing for Go 1.18, 1.19, 1.20, 1.21
- [ ] Include codecov upload step to maintain coverage tracking
- [ ] Add workflow step to run benchmarks (benchmarks/ directory) and comment results on PRs
- [ ] Create .github/workflows/lint.yml for go vet, golangci-lint checks
🌿Good first issues
- Add missing test coverage for any_uint32.go and any_uint64.go—these type files exist but no corresponding test files in any_tests/ (pattern: any_tests/jsoniter_any_*_test.go), so write jsoniter_any_uint32_test.go and jsoniter_any_uint64_test.go covering edge cases like overflow, negative numbers, and zero
- Extend fuzzy_decoder.go documentation and examples—the extra/fuzzy_decoder.go module exists but has no example showing how to register it via config; add a worked example in example_test.go or extra/fuzzy_decoder_test.go showing usage with ConfigCompatibleWithStandardLibrary
- Add benchmarks for custom codecs—benchmarks/ directory tests core performance but doesn't benchmark extra/ codecs (binary_as_string_codec, time_as_int64_codec); add benchmarks/codec_benchmark_test.go comparing their overhead vs. standard paths
⭐Top contributors
Click to expand
Top contributors
- @taowen — 37 commits
- @AllenX2018 — 18 commits
- @molon — 4 commits
- @quasilyte — 4 commits
- [@Rob Figueiredo](https://github.com/Rob Figueiredo) — 3 commits
📝Recent commits
Click to expand
Recent commits
71ac162— Merge pull request #635 from molon/fix-tests (taowen)720cd42— encoding/json: use standard ES6 formatting for numbers during marshal (molon)9b00d50— Revert "std: float64/32 clean up e-09 to e-9" (molon)ffc487c— encoding/json: allow non-string type keys for (un-)marshal (molon)10b9ac0— std: float64/32 clean up e-09 to e-9 (molon)bf8b920— Merge pull request #628 from HassanBaker/upgrade-stretchr (taowen)a7b8414— bumped stretchr to v1.8.0 to get rid of yaml v2 vuln (Hassan Baker)024077e— fix go 1.18 compatibility (Tao Wen)08b5e57— notice incompatibility (taowen)c666182— Merge pull request #562 from runzhi/master (taowen)
🔒Security observations
The json-iterator/go codebase demonstrates reasonable security posture for a JSON parsing library, but has several areas for improvement. Primary concerns include: (1) targeting Go 1.12, a significantly outdated version lacking modern security patches, (2) older dependency versions that should be updated, and (3) custom numeric parsing logic that requires careful review for integer overflow vulnerabilities. The library lacks a formal security policy and documentation of security considerations for parsing untrusted input. No hardcoded credentials, SQL injection risks, XSS vulnerabilities, or Docker/infrastructure issues are evident from the provided file structure. Recommendations focus on modernizing the Go version, updating dependencies, and adding security documentation.
- Medium · Outdated Go Version Target —
go.mod. The module targets Go 1.12, which is significantly outdated (released Feb 2019). This version lacks security patches and bug fixes available in modern Go versions. The latest Go versions include critical security improvements in the standard library and runtime. Fix: Update the Go version requirement to at least 1.21 or later. Update all dependencies to their latest versions compatible with modern Go. - Medium · Dependency: google/gofuzz v1.0.0 —
go.mod. The fuzzing library is pinned to v1.0.0 (released 2018). While used for testing, older fuzzing implementations may not benefit from modern fuzzing improvements and security enhancements in Go's native fuzzing support (Go 1.18+). Fix: Consider migrating to Go's native fuzzing support (available in Go 1.18+) or update google/gofuzz to the latest version. - Low · Missing SECURITY.md or Security Policy —
Repository root. No visible security policy file (SECURITY.md) in the repository. This makes it difficult for security researchers to report vulnerabilities responsibly. Fix: Create a SECURITY.md file with instructions for reporting security vulnerabilities responsibly (e.g., private disclosure process). - Low · Potential Integer Overflow in Numeric Parsing —
any_int32.go, any_int64.go, any_uint32.go, any_uint64.go, iter_int.go, iter_float.go. The presence of multiple numeric type handling files (any_int32.go, any_int64.go, any_uint32.go, any_uint64.go, iter_int.go, iter_float.go) suggests custom numeric parsing logic. Custom numeric parsers are prone to integer overflow/underflow vulnerabilities if not carefully implemented. Fix: Conduct thorough code review and testing of numeric parsing functions. Use fuzzing tests extensively to identify edge cases. Verify handling of boundary values (MAX_INT, MIN_INT, etc.). - Low · Lack of Input Validation Documentation —
iter.go, jsoniter.go. As a JSON parser replacement, the library parses untrusted input. The file structure doesn't reveal explicit input validation documentation or security-first design patterns. Fix: Document security considerations for parsing untrusted JSON input. Include warnings about potential DoS vectors (deeply nested structures, extremely large numbers). Add resource limits to prevent memory exhaustion attacks.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.