jsonfast

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 9, 2026 License: MIT Imports: 6 Imported by: 0

README

go-jsonfast

A zero-allocation JSON builder for Go, optimized for fixed schemas and high-throughput pipelines.

Go Version Go Reference Zero Dependencies

🏗 Architecture Overview

graph TB
    subgraph "Input"
        Fields["Field values"]
        Maps["Nested maps"]
        Times["Timestamps"]
    end

    subgraph "Builder Layer"
        Builder["Builder"]
        Escape["escapeString (SWAR)"]
        IntFmt["appendInt / appendUint"]
        TimeFmt["AddTimeRFC3339Field"]
    end

    subgraph "Output Layer"
        Bytes["Bytes()"]
        Pool["Acquire / Release"]
    end

    subgraph "Batching Layer"
        BatchWriter["BatchWriter (NDJSON)"]
    end

    subgraph "Utilities"
        Flatten["FlattenMap"]
        FlatDirect["AddFlattenedMapField"]
        EscapeStr["EscapeString"]
        IsJSON["IsLikelyJSON"]
    end

    Fields --> Builder
    Maps --> Builder
    Times --> Builder
    Builder --> Escape
    Builder --> IntFmt
    Builder --> TimeFmt
    Builder --> Bytes
    Pool --> Builder
    Bytes --> BatchWriter
    Maps --> Flatten
    Maps --> FlatDirect
    FlatDirect --> Builder

✨ Key Features

  • 🚀 Zero Allocations — all methods operate on a reusable []byte buffer — no copies on the hot path
  • 🧱 Pure Go — no external dependencies, no code generation, no cgo
  • 📋 RFC 8259 Compliant — JSON string escaping with invalid UTF-8 → U+FFFD replacement
  • SWAR String Scanning — word-at-a-time (8 bytes) fast path for safe ASCII runs
  • 🕐 Hand-Written RFC 3339 — time formatting without time.Format allocations
  • 📊 Sorted Map Output — deterministic JSON for caching and deduplication
  • 📦 NDJSON BatchWriter — batch multiple records for message brokers
  • 🗺️ Map Flattening — nested map[string]map[string]string to dot-notation keys
  • 🧬 Fuzz-Tested — continuous Go native fuzzing for escapeString

🚀 Quick Start

📦 Installation
go get github.com/ubyte-source/go-jsonfast

Requires Go 1.25+.

💡 Basic Usage
package main

import (
    "fmt"
    "time"

    "github.com/ubyte-source/go-jsonfast"
)

func main() {
    b := jsonfast.Acquire()
    b.BeginObject()
    b.AddStringField("message", "hello world")
    b.AddIntField("severity", 3)
    b.AddTimeRFC3339Field("timestamp", time.Now())
    b.EndObject()
    data := b.Bytes() // no allocation
    fmt.Println(string(data))
    jsonfast.Release(b) // return to pool
}
🔁 Reuse Without Allocation
b := jsonfast.New(512)

b.BeginObject()
b.AddStringField("k", "v1")
b.EndObject()
process(b.Bytes())

b.Reset() // ready for reuse, no allocation
b.BeginObject()
b.AddStringField("k", "v2")
b.EndObject()
process(b.Bytes())
📦 NDJSON Batching
bw := jsonfast.NewBatchWriter(4096)
b := jsonfast.Acquire()

for _, msg := range messages {
    b.BeginObject()
    b.AddStringField("msg", msg)
    b.EndObject()
    bw.Append(b.Bytes())
    b.Reset()
}

jsonfast.Release(b)
payload := bw.Bytes() // {"msg":"..."}\n{"msg":"..."}\n...
bw.Reset()
� Pre-computed Field Keys

For static field names known at init time, use FieldKey to eliminate per-call quoting overhead (~7% faster):

var (
    keyMessage  = jsonfast.NewFieldKey("message")
    keySeverity = jsonfast.NewFieldKey("severity")
)

b := jsonfast.Acquire()
b.BeginObject()
b.AddStringFieldKey(keyMessage, "hello world")
b.AddIntFieldKey(keySeverity, 3)
b.EndObject()
jsonfast.Release(b)
�🗺️ Map Flattening
nested := map[string]map[string]string{
    "sd@123": {"key1": "val1", "key2": "val2"},
}
flat := jsonfast.FlattenMap(nested, nil)
// flat = {"sd@123.key1": "val1", "sd@123.key2": "val2"}

📖 API Reference

See the package documentation for the full API.

Builder
Function Description
New(capacity int) *Builder Create a new builder with initial capacity
Acquire() *Builder Get a builder from the pool
Release(*Builder) Return a builder to the pool
(*Builder).Reset() Clear for reuse without allocation
(*Builder).Bytes() []byte Get the underlying buffer
(*Builder).Len() int Current buffer length
Field Methods
Method Description
BeginObject() Start a JSON object {
EndObject() End a JSON object }
AddStringField(name, value string) Add "name":"value" with escaping
AddIntField(name string, v int) Add "name":123
AddUint8Field(name string, v uint8) Add "name":255
AddUint16Field(name string, v uint16) Add "name":65535
AddBoolField(name string, v bool) Add "name":true/false
AddNullField(name string) Add "name":null
AddTimeRFC3339Field(name string, t time.Time) Add "name":"2024-01-15T12:30:45Z"
AddRawJSONField(name string, rawJSON []byte) Add "name":<raw> (no escaping)
AddRawJSONFieldString(name, rawJSON string) Same, avoids []byte allocation
AddNestedStringMapField(name string, m map[string]map[string]string) Add nested map as JSON object
AddStringMapObject(m map[string]string, rawJSONKey string) Write map as JSON object
AddFlattenedMapField(m map[string]map[string]string) Write flattened dot-notation fields
Pre-computed FieldKey Methods
Function Description
NewFieldKey(name string) FieldKey Create a pre-computed field key (call at init time)
AddStringFieldKey(k FieldKey, value string) Add "name":"value" using pre-computed key
AddIntFieldKey(k FieldKey, v int) Add "name":123 using pre-computed key
AddInt64FieldKey(k FieldKey, v int64) Add "name":123 using pre-computed key
AddUint64FieldKey(k FieldKey, v uint64) Add "name":123 using pre-computed key
AddBoolFieldKey(k FieldKey, v bool) Add "name":true/false using pre-computed key
AddFloat64FieldKey(k FieldKey, v float64) Add "name":3.14 using pre-computed key
AddTimeRFC3339FieldKey(k FieldKey, t time.Time) Add "name":"..." using pre-computed key
AddRawJSONFieldKey(k FieldKey, rawJSON []byte) Add "name":<raw> using pre-computed key
AddNullFieldKey(k FieldKey) Add "name":null using pre-computed key
Raw Append
Method Description
AppendRaw([]byte) Append raw bytes (no escaping)
AppendRawString(string) Append raw string (no escaping)
AppendEscapedString(string) Append with JSON escaping (zero-alloc)
Scanner (scan.go)
Function Description
IterateFields(data []byte, fn func(key, value []byte) bool) bool Iterate top-level key-value pairs
IterateFieldsString(s string, fn func(key, value []byte) bool) bool Same, accepts string input
FindField(data []byte, key string) ([]byte, bool) Find a field value by key name
FlattenObject(b *Builder, data []byte) bool Recursively flatten nested JSON into Builder
SkipWS(data []byte, i int) int Skip whitespace
SkipValueAt(data []byte, i int) (int, bool) Skip a complete JSON value
SkipStringAt(data []byte, i int) (int, bool) Skip a JSON string (SWAR-accelerated)
SkipBracedAt(data []byte, i int, opener, closer byte) (int, bool) Skip balanced delimiters
Utilities
Function Description
EscapeString(string) string Escape JSON special characters (zero-alloc if no escaping needed)
IsLikelyJSON(string) bool Quick check if string looks like JSON object/array
FlattenMap(m, dst map[string]string) map[string]string Flatten nested map to dot-notation
BatchWriter (NDJSON)
Function Description
NewBatchWriter(capacity int) *BatchWriter Create a new batch writer
(*BatchWriter).Append([]byte) Add a JSON record + newline
(*BatchWriter).AppendString(string) Add a JSON record + newline (string)
(*BatchWriter).Bytes() []byte Get the NDJSON payload
(*BatchWriter).Len() int Current byte length
(*BatchWriter).Count() int Number of records
(*BatchWriter).Reset() Clear for reuse

⚡ Benchmarks

Run with:

make bench

Target: 0 allocs/op on all builder benchmarks, <170 ns/op for a full syslog object.

BenchmarkBuilder_FullSyslogObject-32           34748235     171 ns/op     0 B/op    0 allocs/op
BenchmarkBuilder_FullSyslogObject_FieldKey-32  37712958     161 ns/op     0 B/op    0 allocs/op
BenchmarkBuilder_AddStringField-32             78449582      46 ns/op     0 B/op    0 allocs/op
BenchmarkBuilder_EscapeString_PureASCII-32    100000000      33 ns/op     0 B/op    0 allocs/op
BenchmarkBuilder_AcquireRelease-32            100000000      31 ns/op     0 B/op    0 allocs/op

🧪 Testing

make test        # All tests with race detector
make bench       # Benchmarks with memory profiling
make fuzz        # Native Go fuzzing (30s)
make cover       # Coverage report
make lint        # golangci-lint (25 linters, ultra-strict)

🛡️ Security

The builder enforces bounds to prevent resource exhaustion:

Parameter Limit Constant
Maximum pooled buffer size 256 KiB 1<<18
Maximum flatten depth 64 levels maxFlattenDepth

For security policy and vulnerability reporting, see SECURITY.md.

🧠 Design Principles

  1. Zero-alloc is a constraint, not a goal. It guides every design decision — enforced by benchmarks.
  2. Fixed schemas only. Not a general-purpose JSON encoder — tailored for known field sets.
  3. Deterministic output. Sorted keys for caching and deduplication.
  4. No dependencies. Pure Go, no external libraries, no cgo.
  5. The buffer is the API. Everything writes directly into []byte — no intermediate representations.

📁 Project Structure

go-jsonfast/
├── jsonfast.go         # Builder: zero-alloc JSON builder with pool, escaping, field methods
├── scan.go             # JSON scanner: IterateFields, FindField, FlattenObject, Skip*
├── swar.go             # SWAR constants and detect functions for word-at-a-time scanning
├── flatten.go          # FlattenMap, AddFlattenedMapField: nested map flattening
├── ndjson.go           # BatchWriter: NDJSON record batching
├── doc.go              # Package documentation
├── .golangci.yml       # Ultra-strict linter config (25 linters)
├── Makefile            # Build, test, bench, fuzz, lint
├── CONTRIBUTING.md     # Contribution guidelines
├── SECURITY.md         # Security policy
└── LICENSE             # MIT

🤝 Contributing

Contributions are welcome. Please fork the repository, create a feature branch, and submit a pull request.

For contribution guidelines, see CONTRIBUTING.md.


🔖 Versioning

We use SemVer for versioning. For available versions, see the tags on this repository.


👤 Authors

  • Paolo FabrisInitial workubyte.it

See also the list of contributors who participated in this project.

📄 License

This project is licensed under the MIT License — see the LICENSE file for details.


☕ Support This Project

If go-jsonfast has been useful for your high-throughput pipelines, consider supporting its development:

Buy Me A Coffee


Star this repository if you find it useful.

For questions, issues, or contributions, visit our GitHub repository.

Documentation

Overview

Package jsonfast provides a zero-allocation JSON builder for fixed schemas.

Designed for ultra-high-throughput pipelines (100 Gbps+) where every byte and every nanosecond matters. All methods operate on a reusable byte buffer; steady-state operation requires zero heap allocations.

Features:

  • Zero-alloc Builder with Acquire/Release pool
  • Pre-computed FieldKey for static field names (eliminates per-call quoting)
  • NDJSON BatchWriter for batching records
  • JSON scanner: IterateFields, FindField, FlattenObject (SWAR-accelerated)
  • Flatten nested maps to dot-notation keys
  • Word-at-a-time SWAR string scanning via unsafe for maximum throughput

Usage

b := jsonfast.Acquire()
b.BeginObject()
b.AddStringField("message", "hello world")
b.AddIntField("severity", 3)
b.AddTimeRFC3339Field("timestamp", time.Now())
b.EndObject()
data := b.Bytes() // no allocation
jsonfast.Release(b) // return to pool

Pre-computed Field Keys

For static field names known at init time, use FieldKey to eliminate the per-call quoting overhead:

var keyMessage = jsonfast.NewFieldKey("message")
b.AddStringFieldKey(keyMessage, "hello world")

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func EscapeString

func EscapeString(s string) string

EscapeString returns s with JSON special characters escaped per RFC 8259. If no escaping is needed (pure safe ASCII), it returns s unchanged (zero allocation). Invalid UTF-8 bytes are replaced with U+FFFD, consistent with Builder.escapeString.

Example
package main

import (
	"fmt"

	"github.com/ubyte-source/go-jsonfast"
)

func main() {
	escaped := jsonfast.EscapeString(`She said "hello" and left`)
	fmt.Println(escaped)
}
Output:
She said \"hello\" and left

func FindField

func FindField(data []byte, key string) ([]byte, bool)

FindField finds a top-level field by key name in a JSON object. Returns the raw value bytes and whether the field was found.

func FlattenMap

func FlattenMap(m map[string]map[string]string, dst map[string]string) map[string]string

FlattenMap flattens a nested map[string]map[string]string into a flat map[string]string using dot-notation keys: outer.inner → value. Zero allocation when the result map is provided and has sufficient capacity.

Example:

nested := map[string]map[string]string{
    "sd@123": {"key1": "val1", "key2": "val2"},
}
flat := jsonfast.FlattenMap(nested, nil)
// flat = {"sd@123.key1": "val1", "sd@123.key2": "val2"}
Example
package main

import (
	"fmt"

	"github.com/ubyte-source/go-jsonfast"
)

func main() {
	m := map[string]map[string]string{
		"host": {"name": "fw01", "ip": "10.0.0.1"},
	}
	flat := jsonfast.FlattenMap(m, nil)
	fmt.Println(flat["host.name"])
	fmt.Println(flat["host.ip"])
}
Output:
fw01
10.0.0.1

func FlattenObject

func FlattenObject(b *Builder, data []byte) bool

FlattenObject recursively flattens a nested JSON object into the Builder's current object. Nested objects are recursed up to 64 levels deep; leaf values are emitted as top-level fields. Non-object input is silently skipped. Returns false if the JSON is malformed or nesting exceeds the depth limit.

func IsLikelyJSON

func IsLikelyJSON(s string) bool

IsLikelyJSON reports whether s looks like a JSON object or array. WARNING: checks only the first and last byte — does NOT validate content. SAFETY: the caller MUST ensure upstream validation (e.g. from a trusted parser or json.Valid on ingress) before relying on this to emit raw JSON. Designed for hot-path use where []byte(s) allocation from json.Valid is unacceptable.

Example
package main

import (
	"fmt"

	"github.com/ubyte-source/go-jsonfast"
)

func main() {
	fmt.Println(jsonfast.IsLikelyJSON(`{"key":"value"}`))
	fmt.Println(jsonfast.IsLikelyJSON(`not json`))
}
Output:
true
false

func IterateFields

func IterateFields(data []byte, fn func(key, value []byte) bool) bool

IterateFields calls fn for each top-level key-value pair in a JSON object. key includes quotes, value is the raw JSON bytes. Returns false if the JSON is malformed or fn returns false.

func IterateFieldsString

func IterateFieldsString(s string, fn func(key, value []byte) bool) bool

IterateFieldsString is like IterateFields but accepts a string, avoiding the []byte(string) allocation. The callback slices share the string's backing memory and must not be mutated.

func Release

func Release(b *Builder)

Release returns the Builder to the pool for reuse. The builder must not be used after calling Release. Buffers larger than 256 KB are discarded to bound memory retention.

func ReleaseBatchWriter

func ReleaseBatchWriter(bw *BatchWriter)

ReleaseBatchWriter returns the BatchWriter to the pool for reuse. The writer must not be used after calling ReleaseBatchWriter.

func SkipBracedAt

func SkipBracedAt(data []byte, i int, opener, closer byte) (int, bool)

SkipBracedAt skips a balanced delimiter pair starting at data[i]. Delegates string scanning to SkipStringAt for SWAR throughput. For non-string, non-bracket content, uses SWAR to skip 8 bytes at a time.

func SkipStringAt

func SkipStringAt(data []byte, i int) (int, bool)

SkipStringAt finds the end of a JSON string starting at data[i]. data[i] must be '"'. Returns the index past the closing quote. Rejects raw control chars (< 0x20) per RFC 8259. Uses swarSpecialSkip (see swar.go) for the detection formula.

func SkipValueAt

func SkipValueAt(data []byte, i int) (int, bool)

SkipValueAt skips a complete JSON value starting at data[i]. Returns the index past the value and true, or (i, false) on error.

func SkipWS

func SkipWS(data []byte, i int) int

SkipWS returns the index of the first non-whitespace byte at or after i. Uses a 256-byte lookup table for branch-free classification.

Types

type BatchWriter

type BatchWriter struct {
	// contains filtered or unexported fields
}

BatchWriter accumulates newline-delimited JSON (NDJSON) records into a reusable buffer. Each record is a complete JSON object followed by '\n'.

Designed for high-throughput pipelines that batch multiple log records before sending to a message broker (Redis Streams, Kafka, NATS).

Usage:

bw := jsonfast.NewBatchWriter(4096)
b := jsonfast.Acquire()
b.BeginObject()
b.AddStringField("msg", "hello")
b.EndObject()
bw.Append(b.Bytes())
jsonfast.Release(b)
payload := bw.Bytes()  // "{"msg":"hello"}\n"
bw.Reset()
Example
package main

import (
	"fmt"

	"github.com/ubyte-source/go-jsonfast"
)

func main() {
	bw := jsonfast.NewBatchWriter(256)
	bw.Append([]byte(`{"line":1}`))
	bw.Append([]byte(`{"line":2}`))

	fmt.Print(string(bw.Bytes()))
}
Output:
{"line":1}
{"line":2}

func AcquireBatchWriter

func AcquireBatchWriter() *BatchWriter

AcquireBatchWriter returns a BatchWriter from the pool, ready for use. Call ReleaseBatchWriter when done to return it for reuse.

Example
package main

import (
	"fmt"

	"github.com/ubyte-source/go-jsonfast"
)

func main() {
	bw := jsonfast.AcquireBatchWriter()
	defer jsonfast.ReleaseBatchWriter(bw)

	bw.Append([]byte(`{"pooled":true}`))
	fmt.Print(string(bw.Bytes()))
}
Output:
{"pooled":true}

func NewBatchWriter

func NewBatchWriter(capacity int) *BatchWriter

NewBatchWriter creates a new BatchWriter with the given initial capacity.

func (*BatchWriter) Append

func (w *BatchWriter) Append(record []byte)

Append adds a complete JSON record followed by a newline to the batch.

func (*BatchWriter) AppendString

func (w *BatchWriter) AppendString(record string)

AppendString adds a complete JSON record (as string) followed by a newline.

func (*BatchWriter) Bytes

func (w *BatchWriter) Bytes() []byte

Bytes returns the accumulated NDJSON payload.

func (*BatchWriter) Count

func (w *BatchWriter) Count() int

Count returns the number of records in the batch.

func (*BatchWriter) Grow

func (w *BatchWriter) Grow(n int)

Grow ensures the buffer has at least n bytes of spare capacity. Uses slices.Grow which leverages the runtime's optimized growslice.

func (*BatchWriter) Len

func (w *BatchWriter) Len() int

Len returns the current byte length of the batch.

func (*BatchWriter) Reset

func (w *BatchWriter) Reset()

Reset clears the batch for reuse without releasing memory.

type Builder

type Builder struct {
	// contains filtered or unexported fields
}

Builder is a minimal JSON builder that operates on a reusable byte slice. It avoids allocations by appending directly into the buffer. Not a fully general-purpose JSON writer; tailored for known field sets.

Example
package main

import (
	"fmt"

	"github.com/ubyte-source/go-jsonfast"
)

func main() {
	b := jsonfast.New(256)
	b.BeginObject()
	b.AddStringField("message", "Hello, World!")
	b.AddIntField("severity", 5)
	b.AddBoolField("active", true)
	b.EndObject()

	fmt.Println(string(b.Bytes()))
}
Output:
{"message":"Hello, World!","severity":5,"active":true}
Example (WithTimestamp)
package main

import (
	"fmt"
	"time"

	"github.com/ubyte-source/go-jsonfast"
)

func main() {
	b := jsonfast.New(256)
	ts := time.Date(2024, 3, 15, 14, 30, 45, 0, time.UTC)

	b.BeginObject()
	b.AddStringField("msg", "test")
	b.AddTimeRFC3339Field("ts", ts)
	b.EndObject()

	fmt.Println(string(b.Bytes()))
}
Output:
{"msg":"test","ts":"2024-03-15T14:30:45Z"}

func Acquire

func Acquire() *Builder

Acquire returns a Builder from the pool, ready for use. Call Release when done to return it for reuse.

Example
package main

import (
	"fmt"

	"github.com/ubyte-source/go-jsonfast"
)

func main() {
	b := jsonfast.Acquire()
	defer jsonfast.Release(b)

	b.BeginObject()
	b.AddStringField("source", "pool")
	b.EndObject()

	fmt.Println(string(b.Bytes()))
}
Output:
{"source":"pool"}

func New

func New(capacity int) *Builder

New creates a new builder with initial capacity.

func (*Builder) AddBoolField

func (b *Builder) AddBoolField(name string, v bool)

AddBoolField adds a "name":true/false field.

func (*Builder) AddBoolFieldKey

func (b *Builder) AddBoolFieldKey(k FieldKey, v bool)

AddBoolFieldKey adds a "name":true/false field using a pre-computed key.

func (*Builder) AddFlattenedMapField

func (b *Builder) AddFlattenedMapField(m map[string]map[string]string)

AddFlattenedMapField writes nested map data as flattened "outer.inner":"value" fields directly into the JSON object being built, without materializing an intermediate flat map. Keys are sorted for deterministic output.

Zero allocation for maps with ≤16 total entries (stack-allocated sort buffer).

func (*Builder) AddFloat64Field

func (b *Builder) AddFloat64Field(name string, v float64)

AddFloat64Field adds a "name":float64 field. Integer values are written without decimal point. Fractional values use strconv.AppendFloat with full precision.

Example
package main

import (
	"fmt"

	"github.com/ubyte-source/go-jsonfast"
)

func main() {
	b := jsonfast.New(64)
	b.BeginObject()
	b.AddFloat64Field("pi", 3.14159)
	b.EndObject()

	fmt.Println(string(b.Bytes()))
}
Output:
{"pi":3.14159}

func (*Builder) AddFloat64FieldKey

func (b *Builder) AddFloat64FieldKey(k FieldKey, v float64)

AddFloat64FieldKey adds a "name":float64 field using a pre-computed key.

func (*Builder) AddInt64Field

func (b *Builder) AddInt64Field(name string, v int64)

AddInt64Field adds a "name":int64 field.

func (*Builder) AddInt64FieldKey

func (b *Builder) AddInt64FieldKey(k FieldKey, v int64)

AddInt64FieldKey adds a "name":int64 field using a pre-computed key.

func (*Builder) AddIntField

func (b *Builder) AddIntField(name string, v int)

AddIntField adds a "name":int field.

func (*Builder) AddIntFieldKey

func (b *Builder) AddIntFieldKey(k FieldKey, v int)

AddIntFieldKey adds a "name":int field using a pre-computed key.

func (*Builder) AddNestedStringMapField

func (b *Builder) AddNestedStringMapField(name string, m map[string]map[string]string)

AddNestedStringMapField adds a "name":{"key1":{"k":"v"},"key2":{...}} field. Specifically handles map[string]map[string]string as found in RFC5424 structured data. Keys are sorted to produce deterministic JSON output for caching and deduplication.

func (*Builder) AddNullField

func (b *Builder) AddNullField(name string)

AddNullField adds a "name":null field.

func (*Builder) AddNullFieldKey

func (b *Builder) AddNullFieldKey(k FieldKey)

AddNullFieldKey adds a "name":null field using a pre-computed key.

func (*Builder) AddRawBytesField

func (b *Builder) AddRawBytesField(name, value []byte)

AddRawBytesField adds a "name":value field where name is raw bytes (without quotes) and value is raw JSON bytes. Zero allocation.

func (*Builder) AddRawJSONField

func (b *Builder) AddRawJSONField(name string, rawJSON []byte)

AddRawJSONField adds a "name":<raw json> field without escaping. The value must be valid JSON.

func (*Builder) AddRawJSONFieldKey

func (b *Builder) AddRawJSONFieldKey(k FieldKey, rawJSON []byte)

AddRawJSONFieldKey adds a "name":<raw json> field using a pre-computed key.

func (*Builder) AddRawJSONFieldKeyString

func (b *Builder) AddRawJSONFieldKeyString(k FieldKey, rawJSON string)

AddRawJSONFieldKeyString adds a "name":<raw json string> field using a pre-computed key.

func (*Builder) AddRawJSONFieldString

func (b *Builder) AddRawJSONFieldString(name, rawJSON string)

AddRawJSONFieldString adds a "name":<raw json> field where the raw JSON source is a string. Avoids the []byte(s) allocation of AddRawJSONField.

func (*Builder) AddStringField

func (b *Builder) AddStringField(name, value string)

AddStringField adds a "name":"value" string field with escaping.

func (*Builder) AddStringFieldKey

func (b *Builder) AddStringFieldKey(k FieldKey, value string)

AddStringFieldKey adds a "name":"value" field using a pre-computed key. Eliminates the quoting overhead of fieldKey on every call.

func (*Builder) AddStringMapObject

func (b *Builder) AddStringMapObject(m map[string]string, rawJSONKey string)

AddStringMapObject writes a map[string]string as a JSON object {...} at the current position. Keys are sorted for deterministic output. If rawJSONKey is non-empty, values for that key are embedded as raw JSON when they look like JSON (via IsLikelyJSON). This method does NOT add a field name — it writes just the object.

func (*Builder) AddTimeRFC3339Field

func (b *Builder) AddTimeRFC3339Field(name string, t time.Time)

AddTimeRFC3339Field adds a "name":"RFC3339" field without using time.Format. The output is ALWAYS in UTC (with 'Z' suffix) regardless of the input timezone, because computation uses t.Unix() which is timezone-independent. Uses civil-date arithmetic to avoid double absSec() computation that results from calling both t.Date() and t.Clock().

func (*Builder) AddTimeRFC3339FieldKey

func (b *Builder) AddTimeRFC3339FieldKey(k FieldKey, t time.Time)

AddTimeRFC3339FieldKey adds a "name":"RFC3339" field using a pre-computed key.

func (*Builder) AddUint8Field

func (b *Builder) AddUint8Field(name string, v uint8)

AddUint8Field adds a "name":uint8 field without heap allocation.

func (*Builder) AddUint16Field

func (b *Builder) AddUint16Field(name string, v uint16)

AddUint16Field adds a "name":uint16 field without heap allocation.

func (*Builder) AddUint32Field

func (b *Builder) AddUint32Field(name string, v uint32)

AddUint32Field adds a "name":uint32 field without heap allocation.

func (*Builder) AddUint64Field

func (b *Builder) AddUint64Field(name string, v uint64)

AddUint64Field adds a "name":uint64 field without heap allocation.

func (*Builder) AddUint64FieldKey

func (b *Builder) AddUint64FieldKey(k FieldKey, v uint64)

AddUint64FieldKey adds a "name":uint64 field using a pre-computed key.

func (*Builder) AppendEscapedString

func (b *Builder) AppendEscapedString(s string)

AppendEscapedString appends s with JSON special characters escaped directly into the builder's buffer. Unlike EscapeString, this avoids creating a temporary Builder and string allocation — zero-alloc on the hot path.

func (*Builder) AppendRaw

func (b *Builder) AppendRaw(p []byte)

AppendRaw appends raw bytes to the buffer without any escaping or framing.

func (*Builder) AppendRawString

func (b *Builder) AppendRawString(s string)

AppendRawString appends a raw string to the buffer without any escaping or framing.

func (*Builder) BeginObject

func (b *Builder) BeginObject()

BeginObject starts a JSON object.

func (*Builder) Bytes

func (b *Builder) Bytes() []byte

Bytes returns the underlying buffer (do not modify after use).

func (*Builder) EndObject

func (b *Builder) EndObject()

EndObject ends a JSON object.

func (*Builder) Grow

func (b *Builder) Grow(n int)

Grow ensures the buffer has at least n bytes of spare capacity. Uses slices.Grow which leverages the runtime's optimized growslice, rounding up to size-classes and benefiting from PGO.

Example
package main

import (
	"fmt"

	"github.com/ubyte-source/go-jsonfast"
)

func main() {
	b := jsonfast.New(16)
	b.Grow(1024)
	b.BeginObject()
	b.AddStringField("k", "v")
	b.EndObject()

	fmt.Println(string(b.Bytes()))
}
Output:
{"k":"v"}

func (*Builder) Len

func (b *Builder) Len() int

Len returns the current length of the builder's buffer. Useful for pre-flight capacity checks without calling Bytes().

func (*Builder) Reset

func (b *Builder) Reset()

Reset clears the builder for reuse.

type FieldKey

type FieldKey struct {
	// contains filtered or unexported fields
}

FieldKey is a pre-computed JSON field key prefix. Stores `,"name":` as a single string; the non-comma variant is a substring. Total size: 16 bytes (one string header), same as passing a string argument.

Usage:

var keyMessage = jsonfast.NewFieldKey("message")
b.AddStringFieldKey(keyMessage, "hello")

func NewFieldKey

func NewFieldKey(name string) FieldKey

NewFieldKey creates a pre-computed field key for the given name. The name must be a safe ASCII string (no escaping needed). Call this at init time, not on the hot path.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL