tinywasm/json
A single, platform-agnostic JSON codec for Go that optimizes WebAssembly binary size by using zero reflection. It relies on fmt.Encodable and fmt.Decodable for struct encoding/decoding, which is typically generated by ormc.
Architecture
- Zero Reflection: Uses type switches and visitor pattern instead of the
reflect package.
- Platform-Agnostic: Identical behavior on all platforms (WASM, Linux, macOS, etc.).
- TinyGo Compatible: Optimized for minimal binary size and memory usage.
- 0-Allocation: Hot path is allocation-free (reusing
fmt.Conv buffers and pooling writers/readers).
- Typed Codec: Only types implementing
fmt.Encodable/fmt.Decodable can be directly encoded or decoded.
Usage
Code Generation with ormc
The ormc CLI (from github.com/tinywasm/orm) generates EncodeFields() and DecodeFields() for every struct in the package.
go install github.com/tinywasm/orm/cmd/ormc@latest
ormc # run at the module root; writes/rewrites *_orm.go
Structs
Structs MUST implement fmt.Encodable and fmt.Decodable to be supported. This is handled by generating code with ormc.
package main
import (
"github.com/tinywasm/fmt"
"github.com/tinywasm/json"
)
type User struct {
Name string
}
func (u *User) IsNil() bool { return u == nil }
func (u *User) EncodeFields(w fmt.FieldWriter) {
w.String("name", u.Name)
}
func (u *User) DecodeFields(r fmt.FieldReader) error {
u.Name, _ = r.String("name")
return nil
}
func main() {
u := User{Name: "Alice"}
var out string
if err := json.Encode(&u, &out); err != nil {
panic(err)
}
// out: {"name":"Alice"}
var result User
if err := json.Decode(out, &result); err != nil {
panic(err)
}
}
API
Encode(data fmt.Encodable, output any) error
Serializes to JSON. If data is a collection of objects, it is encoded as a JSON array [...]; otherwise as an object {...}.
- data:
fmt.Encodable → {...} or [...]
- output:
*[]byte, *string, or io.Writer.
Parses JSON into data.
- input:
[]byte, string, or io.Reader.
- data:
fmt.Decodable → expects {...} or [...]
Benchmarks
tinywasm/json is 77% smaller than encoding/json in WASM (~27 KB vs ~119 KB), zero-reflect, and 0-allocation on the serialization hot path.
| Benchmark |
tinywasm/json |
encoding/json |
Δ allocs |
| Encode |
588 ns/op |
555 ns/op |
0 |
| Decode |
1050 ns/op |
2235 ns/op |
-3 |
See full results and analysis in benchmarks/README.md.
Contributing
License
See LICENSE for details.