multijson

package module
v0.0.0-...-c8f61c8 Latest Latest
Warning

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

Go to latest
Published: Jul 10, 2026 License: BSD-3-Clause Imports: 4 Imported by: 0

Documentation

Overview

Package multijson is a pure-Go (no cgo) port of the Ruby multi_json gem: a swappable JSON facade that lets a program pick a JSON adapter at runtime and speak one uniform load/dump API against it.

Backend

The Ruby gem is a thin dispatcher in front of many concrete JSON libraries (oj, yajl, the json gem, ok_json, ...). On a CGO=0 Go target there is exactly one JSON engine worth shipping — the standard library encoding/json — so all of the gem's adapter names (JSONGem, Oj, Yajl, ...) resolve to that single engine. This is faithful: the observable behaviour (parsing, dumping, option handling, error types) matches the gem; only the invisible backend is unified. Calls such as the Ruby MultiJson.use :oj are accepted and honoured (the name is remembered and reported by AdapterName) but behave identically to every other adapter.

Data model

The gem operates on Ruby values; this package operates on the Go values that model them: map[string]any for objects, []any for arrays, string, bool, int64, float64 and nil for scalars. JSON numbers decode to int64 when they are integral and in range, otherwise to float64 (mirroring Ruby's Integer vs Float). The symbolize_keys option is modelled with the distinct key type Symbol: when set, decoded objects are keyed by Symbol instead of string, recursively, which lets a Ruby binding layer (rbgo) tell a symbol-keyed hash from a string-keyed one.

API surface

Load/Decode parse a JSON string; Dump/Encode serialise a Go value. Both accept an optional options map (keys OptSymbolizeKeys, OptPretty, OptAdapter) that is merged over DefaultOptions with per-call keys winning, exactly as the gem merges its default options. Adapter selection is managed with AdapterName, SetAdapter, WithAdapter, CurrentAdapter, DefaultOptions and SetDefaultOptions.

Errors

Invalid JSON yields a *ParseError carrying the offending Data and the underlying Cause (mirroring MultiJson::ParseError, aka MultiJson::LoadError, whose #data and #cause the gem exposes). Selecting an unregistered adapter yields a *AdapterError (the gem's MultiJson::AdapterError, an ArgumentError). A value encoding/json cannot serialise makes Dump return that engine error directly, as the gem lets its adapter's generator error propagate.

Limitations

Because a Ruby Hash is modelled as a Go map, the insertion order of object keys is not preserved on Dump; keys are emitted in the deterministic order encoding/json uses (sorted). The gem preserves Hash insertion order. An order-preserving Ruby hash representation is a concern for the binding layer, not this library.

The package has no dependency on any Ruby runtime: the surface is Go-typed, and a Ruby binding layer marshals Ruby values onto these Go types.

Index

Constants

View Source
const (
	JSONGem             = "json_gem"            // Ruby's stdlib json gem
	JSONPure            = "json_pure"           // json gem's pure-Ruby variant
	Oj                  = "oj"                  // the oj C extension
	Yajl                = "yajl"                // the yajl-ruby C extension
	OkJSON              = "ok_json"             // the bundled fallback parser
	NSJSONSerialization = "nsjsonserialization" // RubyMotion / Cocoa
	Gson                = "gson"                // JRuby, Google gson
	JrJackson           = "jr_jackson"          // JRuby, Jackson
)

Adapter names accepted by the facade. Each mirrors an adapter shipped by the multi_json gem; on this CGO=0 target they all resolve to the single encoding/json backend (see the package doc). Their observable behaviour is identical; only the name reported by AdapterName differs.

View Source
const (
	// OptSymbolizeKeys, when true, keys decoded objects with [Symbol] instead
	// of string (recursively). Mirrors the gem's :symbolize_keys.
	OptSymbolizeKeys = "symbolize_keys"
	// OptPretty, when true, dumps indented JSON. Mirrors the gem's :pretty.
	OptPretty = "pretty"
	// OptAdapter selects an adapter for a single call. Mirrors the gem's
	// :adapter.
	OptAdapter = "adapter"
)

Option keys accepted by Load and Dump, matching the multi_json gem's option symbols.

View Source
const DefaultAdapter = JSONGem

DefaultAdapter is the adapter selected before any SetAdapter call. The gem probes for the fastest available backend; with a unified engine we pick the stdlib json gem name, which is the closest match to encoding/json.

Variables

This section is empty.

Functions

func AdapterName

func AdapterName() string

AdapterName reports the name of the currently selected adapter (the gem's MultiJson.adapter, reduced to its name).

func Decode

func Decode(s string, opts ...map[string]any) (any, error)

Decode is an alias for Load, mirroring MultiJson.decode.

func DefaultOptions

func DefaultOptions() map[string]any

DefaultOptions returns a copy of the default options merged into every Load/Dump call, mirroring MultiJson.default_options.

func Dump

func Dump(obj any, opts ...map[string]any) (string, error)

Dump serialises a Go value to a JSON string. Options are merged over DefaultOptions with per-call keys winning. Mirrors MultiJson.dump.

func Encode

func Encode(obj any, opts ...map[string]any) (string, error)

Encode is an alias for Dump, mirroring MultiJson.encode.

func Load

func Load(s string, opts ...map[string]any) (any, error)

Load parses a JSON string into a Go value. Options are merged over DefaultOptions with per-call keys winning. Mirrors MultiJson.load.

func SetAdapter

func SetAdapter(name string) error

SetAdapter selects the adapter used by subsequent Load/Dump calls, mirroring MultiJson.use / MultiJson.adapter=. An empty name selects DefaultAdapter; an unknown name returns a *AdapterError.

func SetDefaultOptions

func SetDefaultOptions(opts map[string]any)

SetDefaultOptions replaces the default options merged into every Load/Dump call, mirroring MultiJson.default_options=. A nil map clears them.

func WithAdapter

func WithAdapter(name string, fn func() error) error

WithAdapter runs fn with name selected as the current adapter, restoring the previous adapter afterwards, mirroring MultiJson.with_adapter. If name cannot be resolved, fn is not run and the *AdapterError is returned.

Types

type Adapter

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

Adapter is a resolved JSON adapter. Every adapter shares the encoding/json engine; the name is retained for [Name] and AdapterName reporting.

func CurrentAdapter

func CurrentAdapter(opts ...map[string]any) (Adapter, error)

CurrentAdapter resolves the adapter for a set of call options: the OptAdapter key overrides the current adapter, mirroring MultiJson.current_adapter. An unknown override returns a *AdapterError.

func (Adapter) Dump

func (a Adapter) Dump(obj any, opts map[string]any) (string, error)

Dump serialises a Go value to a JSON string, honouring the pretty option. A value the engine cannot serialise makes Dump return that engine error directly, as the gem lets its generator error propagate.

func (Adapter) Load

func (a Adapter) Load(s string, opts map[string]any) (any, error)

Load parses a JSON string into a Go value, honouring the symbolize_keys option. A parse failure is wrapped in a *ParseError carrying the input and the underlying cause, exactly as the gem wraps adapter errors.

func (Adapter) Name

func (a Adapter) Name() string

Name reports the adapter's registered name.

type AdapterError

type AdapterError struct {
	// Name is the adapter specification that could not be resolved.
	Name string
	// Cause is the underlying failure, if any (the gem wraps a LoadError/NameError).
	Cause error
}

AdapterError models MultiJson::AdapterError, the ArgumentError the gem raises when an adapter cannot be recognised or loaded. Name is the rejected adapter specification and Cause, when present, is the underlying failure.

func (*AdapterError) Error

func (e *AdapterError) Error() string

Error implements the error interface with a message shaped like the gem's AdapterError.build output.

func (*AdapterError) Unwrap

func (e *AdapterError) Unwrap() error

Unwrap exposes the underlying cause, if any.

type LoadError

type LoadError = ParseError

LoadError is the alias the gem defines as MultiJson::LoadError = ParseError.

type ParseError

type ParseError struct {
	// Data is the input string that failed to parse (the gem's #data).
	Data string
	// Cause is the underlying engine error (the gem's #cause).
	Cause error
}

ParseError models MultiJson::ParseError (aliased in the gem as MultiJson::LoadError and MultiJson::DecodeError): the error raised when an adapter fails to parse a JSON string. It carries the offending input in Data and the underlying engine error in Cause, mirroring the gem's #data and #cause readers.

func (*ParseError) Error

func (e *ParseError) Error() string

Error implements the error interface, reporting the underlying cause's message, as MultiJson::ParseError forwards the wrapped exception's message.

func (*ParseError) Unwrap

func (e *ParseError) Unwrap() error

Unwrap exposes the underlying cause so errors.Is/errors.As can reach it.

type Symbol

type Symbol string

Symbol is the key type used for decoded objects when OptSymbolizeKeys is set, modelling a Ruby Symbol so a binding layer can distinguish a symbol-keyed hash from a string-keyed one.

Jump to

Keyboard shortcuts

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