Fast JSON decoding for Go, generated from your types. Lightning writes
reflection-free UnmarshalJSON methods and provides a toolkit for reading,
streaming, editing, and validating JSON without a schema.
Quick start · Documentation · Run an example in your browser · Benchmarks · Contributing
- Keep your Go types and call sites. Generated methods implement
json.Unmarshaler;encoding/json.Unmarshalcalls them automatically. Callv.UnmarshalJSON(data)directly to skip that entry point. - Control allocations. Reuse slices, maps, and pointers across decodes. Opt into string aliasing or in-place unescaping when you own the input buffer.
- Use the CPU you have. Runtime dispatch selects SIMD scanners on amd64 and arm64, with portable fallbacks on other architectures.
- Read only what you need. The public
pkg/jsontoolkit looks up paths, walks arrays, streams large documents, and edits raw JSON without generation.
Lightning has deliberate differences from encoding/json, including exact key
matching, null handling, and numeric overflow. Read the
compatibility guide before migrating.
Requires Go 1.25 or newer. In a new directory:
go mod init example.com/events
go get github.com/JohanLindvall/lightning@latestSave this as event.go:
package main
import (
"fmt"
"log"
"time"
)
//go:generate go run github.com/JohanLindvall/lightning $GOFILE
type Event struct {
ID int64 `json:"id"`
Kind string `json:"kind"`
At time.Time `json:"at"`
Tags []string `json:"tags"`
}
func main() {
data := []byte(`{"id":42,"kind":"deploy","at":"2026-10-01T12:00:00Z","tags":["prod"]}`)
var e Event
if err := e.UnmarshalJSON(data); err != nil {
log.Fatal(err)
}
fmt.Println(e.ID, e.Kind, e.At.Format(time.RFC3339), e.Tags)
}Generate the decoder and run it:
go generate ./...
go mod tidy
go run .
# 42 deploy 2026-10-01T12:00:00Z [prod]Generation writes event_unmarshal.go beside your schema. The directive uses the
version in your go.mod, keeping the generator and its runtime together. Run
go generate ./... again after changing the schema or upgrading Lightning.
See the generator guide for installation options, supported
types, reuse, and custom unmarshalers, or tags and directives
for nocopy, strict, emptyslice, lax, and other options.
Import github.com/JohanLindvall/lightning/pkg/json to work directly with bytes.
Install it in your module:
go get github.com/JohanLindvall/lightning/pkg/json@latestThis standalone example looks up a nested string:
package main
import (
"fmt"
"log"
json "github.com/JohanLindvall/lightning/pkg/json"
)
func main() {
data := []byte(`{"user":{"name":"Ada"}}`)
raw, err := json.Lookup(data, "user", "name")
if err != nil {
log.Fatal(err)
}
name, err := json.String(raw)
if err != nil {
log.Fatal(err)
}
fmt.Println(name) // Ada
}Lookup results alias the input; keep it unchanged while using them. Use the
checked edit functions when editing untrusted
input. Valid follows Lightning's documented grammar; it is not a substitute for
encoding/json.Valid when you need exactly the standard library's acceptance rules.
| I want to… | Start here |
|---|---|
| Generate a decoder or reuse a target | Generator guide |
| Configure tags and directives | Options reference |
| Look up values, validate, escape, or parse | JSON toolkit · API reference |
| Process a large response as it arrives | Streaming |
| Set values or remove defaults | Editing JSON |
| Check migration and buffer ownership rules | Compatibility and input contracts |
| Understand CPU support or measure performance | Performance guide |
| Work on Lightning itself | Contributing · Repository layout |
The comparison suite covers real-world documents and synthetic workloads, with
generated decoders, DecodeAny, encoding/json, easyjson, sonic, goccy/go-json,
and json/v2. It reports latency, bytes allocated, and allocation counts.
| Architecture | Decoder comparisons | Toolkit and runtime benchmarks |
|---|---|---|
| amd64 | Results | Results |
| arm64 | Results | Results |
These are single-run CI snapshots, not a guarantee for your workload. Check the CPU and toolchain headers, compare same-run ratios, and measure your own data. The performance guide explains how to reproduce the suite.
Questions, bug reports, documentation fixes, tests, and performance work are welcome. Open an issue with a small example, or follow CONTRIBUTING.md to run the project and prepare a pull request. You can try the runnable examples without installing anything.
If Lightning helps your project, a star helps other Go developers discover it.
MIT © Johan Lindvall. See the credits for algorithms and benchmark sources.