Documentation
¶
Overview ¶
Package jsontransform provides streaming JSON transformation with field renaming and value transformation.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Option ¶
type Option func(*Transformer)
Option configures a Transformer.
func WithKeepRenamedOriginal ¶
func WithKeepRenamedOriginal() Option
WithKeepRenamedOriginal makes renaming additive instead of destructive: when a field is renamed, the original field name is emitted alongside the new one, carrying the input value untransformed. Use it to add a transformed field to a payload while keeping the field older consumers still read:
{"counter_id":"ST/HK/00700"} → {"counter_id":"ST/HK/00700","symbol":"700.HK"}
The original comes first and is written verbatim — value transformations and nested rename rules apply only to the renamed copy, so the retained field keeps exactly the shape the input had.
Three cases are deliberately left alone. A field whose name does not change is emitted once: an in-place value transformation cannot keep both values under one key. A field omitted by a rename callback (rename to "") stays omitted — omission is a deletion, not a rename. And renaming two sibling fields onto each other's names still produces duplicate keys, exactly as it does without this option; the library never deduplicates output keys.
func WithPathRenameFunc ¶
func WithPathRenameFunc(fn PathRenameFunc) Option
WithPathRenameFunc sets a path-based rename callback. It takes precedence over WithRenameFunc for fields whose path it matches (returns non-nil).
func WithPathValueTransformer ¶
func WithPathValueTransformer(fn func(path string) ValueTransformFunc) Option
WithPathValueTransformer sets a path-based value-transform callback. It takes precedence over WithValueTransformer for paths it matches.
func WithRenameFunc ¶
func WithRenameFunc(fn RenameFunc) Option
WithRenameFunc sets a function to rename object field names.
func WithValueTransformer ¶
func WithValueTransformer(fn func(fieldName string) ValueTransformFunc) Option
WithValueTransformer sets a function called once per unique field name to determine whether and how to transform its value. Return nil to leave the value unchanged for that field (fast path, no materialisation).
type PathRenameFunc ¶
PathRenameFunc is called for each object field with its root-anchored, dot-joined path (array levels are transparent). Return nil to fall back to the name-based RenameFunc, or a *string with the new leaf name ("" omits the field).
type RenameFunc ¶
RenameFunc is called for each object field name. Return nil to keep the original name, or a *string with the new name to rename it.
func CamelCaseRename ¶
func CamelCaseRename() RenameFunc
CamelCaseRename returns a RenameFunc that converts all field names to lowerCamelCase. Example: "user_name" → "userName"
func KebabCaseRename ¶
func KebabCaseRename() RenameFunc
KebabCaseRename returns a RenameFunc that converts all field names to kebab-case. Example: "UserName" → "user-name"
func MapRename ¶
func MapRename(m map[string]string) RenameFunc
MapRename returns a RenameFunc that renames fields according to the given map. Fields not found in the map are not renamed (returns nil). Can be combined with other RenameFuncs for fallback behavior.
func PascalCaseRename ¶
func PascalCaseRename() RenameFunc
PascalCaseRename returns a RenameFunc that converts all field names to PascalCase. Example: "user_name" → "UserName"
func SnakeCaseRename ¶
func SnakeCaseRename() RenameFunc
SnakeCaseRename returns a RenameFunc that converts all field names to snake_case. Example: "UserName" → "user_name"
type Transformer ¶
type Transformer struct {
// contains filtered or unexported fields
}
Transformer performs JSON transformation with optional field renaming and value transformation. A Transformer is safe for concurrent use after construction.
func New ¶
func New(opts ...Option) *Transformer
New creates a new Transformer with the given options.
Example (MapRenameWithFallback) ¶
ExampleNew_mapRenameWithFallback demonstrates combining MapRename with a fallback.
package main
import (
"fmt"
jsontransform "github.com/longbridge/json-transformer"
)
func main() {
exact := jsontransform.MapRename(map[string]string{"id": "ID"})
fallback := jsontransform.SnakeCaseRename()
t := jsontransform.New(
jsontransform.WithRenameFunc(func(name string) *string {
if s := exact(name); s != nil {
return s
}
return fallback(name)
}),
)
out, _ := t.TransformBytes(`{"id":1,"userName":"Alice"}`)
fmt.Println(string(out))
}
Output: {"ID":1,"user_name":"Alice"}
Example (MaskField) ¶
ExampleNew_maskField demonstrates renaming a field and masking its value.
package main
import (
"fmt"
jsontransform "github.com/longbridge/json-transformer"
)
func main() {
t := jsontransform.New(
jsontransform.WithRenameFunc(func(name string) *string {
if name == "pwd" {
s := "password"
return &s
}
return nil
}),
jsontransform.WithValueTransformer(func(name string) jsontransform.ValueTransformFunc {
if name == "pwd" {
return func(v any) any { return "***" }
}
return nil
}),
)
out, _ := t.TransformBytes(`{"user":"alice","pwd":"secret"}`)
fmt.Println(string(out))
}
Output: {"user":"alice","password":"***"}
Example (PatternMatch) ¶
ExampleNew_patternMatch demonstrates matching fields by suffix to reformat timestamps.
package main
import (
"encoding/json"
"fmt"
"strings"
"time"
jsontransform "github.com/longbridge/json-transformer"
)
func main() {
t := jsontransform.New(
jsontransform.WithValueTransformer(func(name string) jsontransform.ValueTransformFunc {
if strings.HasSuffix(name, "_at") {
return func(v any) any {
if n, ok := v.(json.Number); ok {
ts, _ := n.Int64()
return time.Unix(ts, 0).UTC().Format(time.RFC3339)
}
return v
}
}
return nil
}),
)
out, _ := t.TransformBytes(`{"name":"Alice","created_at":1700000000}`)
fmt.Println(string(out))
}
Output: {"name":"Alice","created_at":"2023-11-14T22:13:20Z"}
Example (RenameSnakeCase) ¶
ExampleNew_renameSnakeCase demonstrates renaming camelCase keys to snake_case.
package main
import (
"fmt"
jsontransform "github.com/longbridge/json-transformer"
)
func main() {
t := jsontransform.New(jsontransform.WithRenameFunc(jsontransform.SnakeCaseRename()))
out, _ := t.TransformBytes(map[string]any{"userName": "Alice", "userAge": 30})
fmt.Println(string(out))
// Note: map key order is non-deterministic; output may vary.
}
Output:
func (*Transformer) Transform ¶
func (t *Transformer) Transform(src any, dst io.Writer) error
Transform transforms src and writes the result to dst.
src dispatch:
- map[string]any → fast path (in-memory traversal, no marshal/unmarshal)
- struct / *struct → fast path (reflection with field-metadata cache)
- slice / array → fast path
- []byte / string / io.Reader → streaming path (token-based)
- other primitive types → encoded directly
func (*Transformer) TransformBytes ¶
func (t *Transformer) TransformBytes(src any) ([]byte, error)
TransformBytes transforms src and returns the result as []byte. It uses pooled buffers for efficiency.
func (*Transformer) TransformStream ¶
TransformStream processes multiple whitespace-separated JSON values from r and writes transformed results to w, one per line (suitable for NDJSON).
Example ¶
ExampleTransformer_TransformStream demonstrates processing NDJSON line by line.
package main
import (
"fmt"
"strings"
jsontransform "github.com/longbridge/json-transformer"
)
func main() {
t := jsontransform.New(jsontransform.WithRenameFunc(jsontransform.SnakeCaseRename()))
r := strings.NewReader(`{"userId":1}` + "\n" + `{"userId":2}`)
var buf strings.Builder
_ = t.TransformStream(r, &buf)
fmt.Println(buf.String())
}
Output: {"user_id":1} {"user_id":2}
type ValueTransformFunc ¶
ValueTransformFunc transforms a decoded Go value (string/float64/bool/nil/map/slice).