json

package module
v0.0.0-...-0a3481c Latest Latest
Warning

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

Go to latest
Published: May 2, 2026 License: MIT Imports: 14 Imported by: 13

README

go-json

Package json implements JSON encoders and decoders, for the Go programming-language (golang).

Package json is meant to be a replacement for the Go built-in "encoding/json" package.

Package json also includes a number of addtional useful features (that the Go built-in "encoding/json" package does not have).

Package json is a custom JSON encoding/decoding library for the Go programming-language (golang), designed as a replacement for the Go built-in"encoding/json" package with additional features like custom modifiers, constant fields, and extended struct tag support.

Documention

Online documentation, which includes examples, can be found at: http://godoc.org/github.com/reiver/go-json

GoDoc

Examples

To marshal a Go value to JSON, you can do something similar to the following:

import "github.com/reiver/go-json"

// ...

jsonBytes, err := json.Marshal(value)

To unmarshal a JSON value to Go, you can do something similar to the following:

import "github.com/reiver/go-json"

// ...

err := json.Unmarshal(jsonBytes, &value)

Custom Modifiers

Package json supports custom modifiers through struct tags. A modifier transforms the already-marshaled JSON bytes of a struct field.

Tag Format
Field Type `json:"name,modifier1,modifier2,..."`

Any struct tag option that isn't omitempty, nullempty, or - is treated as a modifier name. Multiple modifiers are applied in order, left to right.

Built-in Modifiers

The DefaultUsher (used by json.Marshal) comes with two built-in modifiers:

string — wraps the marshaled value in quotes:

type MyStruct struct {
	Banana int `json:"banana,string"`
}

// Banana with value 5 produces: {"banana":"5"}

bare — strips quotes from a JSON string, outputting the raw content:

type MyStruct struct {
	Banana string `json:"banana,bare"`
}

// Banana with value "true" produces: {"banana":true}
Registering Custom Modifiers

You can register your own modifiers on an Usher instance:

var usher json.Usher

usher.ImplantModifier("digest", func(data []byte) ([]byte, error) {
	// transform the marshaled bytes
	// ...
	return transformed, nil
})

jsonBytes, err := usher.Marshal(value)

A ModifierFunc has the signature func([]byte) ([]byte, error). It receives the marshaled JSON bytes for a field and returns the transformed bytes.

Modifiers can be chained:

Field string `json:"field,omitempty,string,mymod"`

This applies string first, then mymod. If any modifier returns an ErrorEmpty error and the field has omitempty, the field is omitted from the output. If the field has nullempty instead, the field outputs null.

To add a custom modifier to the global DefaultUsher (so it works with json.Marshal):

json.DefaultUsher.ImplantModifier("mymod", myModifierFunc)

Null Empty (nullempty)

The nullempty struct tag option outputs JSON null for a field when its value is empty, instead of omitting the field entirely (which is what omitempty does).

type MyStruct struct {
	Name  string   `json:"name"`
	Value string   `json:"value,nullempty"`
	Items []string `json:"items,nullempty"`
}

// With zero values produces: {"name":"","value":null,"items":null}

Emptiness is determined using the same checks as omitempty:

  • Types implementing Emptier (IsEmpty() bool)
  • Types implementing Nothinger (IsNothing() bool)
  • Zero values (via reflect.DeepEqual)
  • Empty slices, maps, and arrays (length 0)

When a type implements Emptier or Nothinger, that interface is trusted and the fallback zero-value/length checks are not applied.

If a MarshalJSON() method or a modifier returns an ErrorEmpty error and the field has nullempty, the field outputs null instead of being omitted.

Installation

To install package json do the following:

GOPROXY=direct go get github.com/reiver/go-json

Author

Package json was written by Charles Iliya Krempeaux

Documentation

Index

Constants

View Source
const (
	ErrModifierNotReversible = erorr.Error("json: modifier is not reversible")
	ErrNilReceiver           = erorr.Error("json: nil receiver")
	ErrNotBool               = erorr.Error("json: not bool")
	ErrNotJSONNumber         = erorr.Error("json: not JSON number")
)

Variables

This section is empty.

Functions

func BareModifierFunc

func BareModifierFunc(bytes []byte) ([]byte, error)

BareModifierFunc is the modifier that, in the DefaultUsher, is the implementation behind the "bare" modifier.

For example:

struct {

	// ...

	Banana string `json:"banana,bare"`

	// ...

}

func Compact

func Compact(dst io.Writer, src []byte) error

func ErrEmpty

func ErrEmpty(message string) error

ErrEmpty returns an error of type ErrorEmpty.

ErrorEmpty is used with the "omitempty" struct-field tag option.

func Marshal

func Marshal(value any) ([]byte, error)

Marshal returns the JSON version of 'value'.

For example:

bytes, err := json.Marshal(value)

See Usher.Marshal for more information.

Calling:

bytes, err := json.Marshal(value)

Is the same as calling:

bytes, err := json.DefaultUsher.Marshal(value)

json.Marshal() is a convenience function for json.DefaultUsher.Marshal().

func MarshalBool

func MarshalBool(value bool) []byte

MarshalBool returns the JSON version of a Go bool.

func MarshalFloat32

func MarshalFloat32(value float32) []byte

MarshalFloat32 returns the JSON version of a Go float32.

func MarshalFloat64

func MarshalFloat64(value float64) []byte

MarshalFloat64 returns the JSON version of a Go float64.

func MarshalInt

func MarshalInt(value int) []byte

MarshalInt returns the JSON version of a Go int.

func MarshalInt8

func MarshalInt8(value int8) []byte

MarshalInt8 returns the JSON version of a Go int8.

func MarshalInt16

func MarshalInt16(value int16) []byte

MarshalInt16 returns the JSON version of a Go int16.

func MarshalInt32

func MarshalInt32(value int32) []byte

MarshalInt32 returns the JSON version of a Go int32.

func MarshalInt64

func MarshalInt64(value int64) []byte

MarshalInt64 returns the JSON version of a Go uint64.

func MarshalSlice

func MarshalSlice[T any](value []T) ([]byte, error)

MarshalSlice returns the JSON version of a Go slice.

func MarshalString

func MarshalString(value string) []byte

MarshalString returns the JSON version of a Go string.

func MarshalTextMarshaler

func MarshalTextMarshaler(textMarshaler encoding.TextMarshaler) ([]byte, error)

MarshalTextMarshaler returns the JSON version of the successful result from encoding.TextMarshaler..

func MarshalUint

func MarshalUint(value uint) []byte

MarshalUint returns the JSON version of a Go uint.

func MarshalUint8

func MarshalUint8(value uint8) []byte

MarshalUint8 returns the JSON version of a Go uint8.

func MarshalUint16

func MarshalUint16(value uint16) []byte

MarshalUint16 returns the JSON version of a Go uint16.

func MarshalUint32

func MarshalUint32(value uint32) []byte

MarshalUint32 returns the JSON version of a Go uint32.

func MarshalUint64

func MarshalUint64(value uint64) []byte

MarshalUint64 returns the JSON version of a Go uint64.

func MergeAndMarshal

func MergeAndMarshal(values ...any) ([]byte, error)

Marshal return the JSON version of 'value'.

func NormalizeNumberBytes

func NormalizeNumberBytes(bytes []byte) []byte

NormalizeNumberBytes normalizes a JSON number. It expands scientific notation into plain decimal form (e.g., "3.7e-5" becomes "0.000037"), strips leading '+', unnecessary leading zeros, trailing zeros after a decimal point, and a trailing decimal point. A negative sign is preserved when appropriate.

NormalizeNumberBytes is similar to NormalizeNumberString except it accepts and returns a []byte (rather than a string).

See also: Number.

func NormalizeNumberString

func NormalizeNumberString(str string) string

NormalizeNumberString normalizes a JSON number. It expands scientific notation into plain decimal form (e.g., "3.7e-5" becomes "0.000037"), strips leading '+', unnecessary leading zeros, trailing zeros after a decimal point, and a trailing decimal point. A negative sign is preserved when appropriate.

NormalizeNumberString is similar to NormalizeNumberBytes except it accepts and returns a string (rather than a []byte).

See also: Number.

func ObstructedUnmarshal

func ObstructedUnmarshal(data []byte, dst any) error

ObstructedUnmarshal deserializes JSON data strictly. Returns an error if unknown JSON fields are encountered.

It is equivalent to calling DefaultUsher.ObstructedUnmarshal().

func StringModifierFunc

func StringModifierFunc(bytes []byte) ([]byte, error)

StringModifierFunc is the modifier that, in the DefaultUsher, is the implementation behind the "string" modifier.

For example:

struct {

	// ...

	Banana int `json:"banana,string"`

	// ...

}

func Unmarshal

func Unmarshal(data []byte, dst any) error

Unmarshal deserializes JSON data into the value pointed to by dst. Unknown JSON fields are silently ignored.

It is equivalent to calling DefaultUsher.Unmarshal().

func UnmarshalBool

func UnmarshalBool(bytes []byte, dst *bool) error

UnmarshalBool JSON-unmarshals a JSON bool into a Go bool.

func UnmarshalInt

func UnmarshalInt(data []byte, dst *int) error

func UnmarshalInt8

func UnmarshalInt8(data []byte, dst *int8) error

func UnmarshalInt16

func UnmarshalInt16(data []byte, dst *int16) error

func UnmarshalInt32

func UnmarshalInt32(data []byte, dst *int32) error

func UnmarshalInt64

func UnmarshalInt64(data []byte, dst *int64) error

func UnmarshalString

func UnmarshalString(data []byte, dst *string) error

UnmarshalString JSON-unmarshals a JSON string into a Go string.

func UnmarshalUint

func UnmarshalUint(data []byte, dst *uint) error

func UnmarshalUint8

func UnmarshalUint8(data []byte, dst *uint8) error

func UnmarshalUint16

func UnmarshalUint16(data []byte, dst *uint16) error

func UnmarshalUint32

func UnmarshalUint32(data []byte, dst *uint32) error

func UnmarshalUint64

func UnmarshalUint64(data []byte, dst *uint64) error

func UnobstructedUnmarshal

func UnobstructedUnmarshal(data []byte, dst any) error

UnobstructedUnmarshal deserializes JSON data permissively. It allows trailing commas, comments, and leading plus-signs. Unknown JSON fields are silently ignored.

It is equivalent to calling DefaultUsher.UnobstructedUnmarshal().

func UnobstructedUnmarshalBool

func UnobstructedUnmarshalBool(bytes []byte, dst *bool) error

UnobstructedUnmarshal JSON-unmarshals a JSON bool into a Go bool. It ignore the letter-casing of "true" and "false", (also) accepts "t" and "f", and (also) accepts "1" and "0".

Types

type Const

type Const[T any] struct{}

Const is used to include a constant field in a struct.

For example:

type AcitivtyLink struct {
	HRef            string  `json:"href"`
	MediaType       string  `json:"mediatype"`
	Rel             string  `json:"rel"`
	Rev             string  `json:"rev"`
	Type json.Const[string] `json:"type" json.value:"Link"` // <----------
}

Here is another example:

type Manitoban struct {
	GivenName               string  `json:"given-name"`
	AdditionalNames       []string  `json:"additional-names,omitempty"`
	FamilyName              string  `json:"family-name"`
	HomeCountry  json.Const[string] `json:"home-country"  json.value:"Canada"`   // <----------
	HomeProvince json.Const[string] `json:"home-province" json.value:"Manitoba"` // <----------
	HomeCity                string  `json:"home-city"`
}

func (Const[T]) DecodeFromString

func (Const[T]) DecodeFromString(str string) (any, error)

See the Constantizer interface documentation for details.

func (Const[T]) JSONConst

func (Const[T]) JSONConst()

See the Constantizer interface documentation for details on why this exists.

type ConstMismatchError

type ConstMismatchError struct {
	Path      string
	FieldName string
	Expected  any
	Actual    any
}

ConstMismatchError is returned when a JSON value does not match the expected Const[T] value declared in the json.value struct tag.

func (ConstMismatchError) Error

func (e ConstMismatchError) Error() string

type Constantizer

type Constantizer interface {

	// JSONConst is a dummy-method used (along with the method DecodeFromString) to specify that something is of inteface type json.Constantizer.
	//
	// An implementation of it will look similar to this:
	//
	//	func (receiver MyType) JSONConst() {
	//		// nothing here
	//	}
	JSONConst()

	// DecodeFromString decodes the value of a string to the underlying type.
	//
	// The value will come from the value of the struct tag: "json.value".
	//
	//
	// For example:
	//
	//	type MyType struct {
	//
	//		// ...
	//
	//		MyField json.Const[uint64] `json:"myfield" json.value:"123"`
	//
	//		// ...
	//
	//	}
	DecodeFromString(string) (any, error)
}

type Emptier

type Emptier interface {
	IsEmpty() bool
}

Emptier works with the `omitempty` struct-tag, recognized by Marshal and Usher.Marshal.

For example, a custom type might look like:

type MyType struct {
	// ...
}

func (receiver MyType) IsEmpty() bool {
	// ...
}

And it might be used similar to the following:

var MyStruct struct {
	Apple  string `json:"apple,omitempty"`
	Banana MyType `json:"banana,omitempty"` // <---------
	Cherry int    `json:"cherry"`
}

// ...

var value MyStruct // = ...

bytes, err := json.Marshal(value)

An alternative to Emptier is Nothinger, which is more commonly used with optional-types (i.e., optiona-types).

type ErrorEmpty

type ErrorEmpty interface {
	error
	ErrorEmpty()
}

ErrorEmpty is a special type of error.

ErrorEmpty is used with the "omitempty" struct-field tag option.

If a (custom) type's MarshalJSON() function returns an error of type ErrorEmpty, and a field of that type has the "omitempty" struct-field tag option then, that field will be omitted in the marshaled-JSON.

You can, of course, create your own (custom) error type that fits this ErrorEmpty interface, or you can use the ErrEmpty to create that ErrorEmpty error for you.

type Marshaler

type Marshaler interface {
	MarshalJSON() ([]byte, error)
}

Marshaler is something that can marshal itself into JSON.

type ModifierFunc

type ModifierFunc func([]byte) ([]byte, error)

ModifierFunc is the type of a modifer.

Modifers as used to modify the the a marshaled struct-field.

type Nothinger

type Nothinger interface {
	IsNothing() bool
}

Nothinger is similar to Emptier, but is more commonly used with optional-types (i.e., optiona-types).

I.e., an optional-type has "something" in it or "nothing" in it. (Some optional-types call this "some" and "none".) A optional-type might have a method IsNothing()bool to communicate whether it has "nothing" or "something" in it.

If the optional-type has such a IsNothing()bool method, then Marshal and Usher.Marshal make use of that method for the purposes of `omitempty`.

If you type in not an optional-type, then it should probably instead implement Emptier.

type Number

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

Number represents a JSON number. It stores it as a string to avoid precision loss that comes from using float64.

See also: NormalizeNumberString.

func MustParseNumberString

func MustParseNumberString(jsonNumber string) Number

func ParseNumberString

func ParseNumberString(jsonNumber string) (Number, bool)

ParseNumberString returns a Number with the value of a JSON number. The second return value is false if jsonNumber is not a valid JSON number.

func Zero

func Zero() Number

Zero returns a Number with a value of zero (0).

func (Number) Float64

func (receiver Number) Float64() (float64, bool)

Float64 returns the number as a float64. The second return value is false if the number cannot be represented as a float64.

func (Number) Int64

func (receiver Number) Int64() (int64, bool)

Int64 returns the number as an int64. The second return value is false if the number cannot be represented as an int64.

func (Number) MarshalJSON

func (receiver Number) MarshalJSON() ([]byte, error)

MarshalJSON returns the JSON encoding of the number.

String makes Number fit the Marshaler interface.

func (Number) String

func (receiver Number) String() string

String returns the string representation of the number.

String makes Number fit the fmt.Stringer interface.

func (Number) Uint64

func (receiver Number) Uint64() (uint64, bool)

Uint64 returns the number as a uint64. The second return value is false if the number cannot be represented as a uint64.

func (*Number) UnmarshalJSON

func (receiver *Number) UnmarshalJSON(data []byte) error

UnmarshalJSON sets the number from a JSON number literal. Returns an error if data is not a valid JSON number.

UnmarshalJSON makes Number fit the Unmarshaler interface.

type OmitAlways

type OmitAlways interface {
	JSONOmitAlways()
}

A field in a struct and a value in a map that fits this interface (by having the method JSONOmitAlways()) will always be omitted from the result JSON.

type UnknownFieldError

type UnknownFieldError struct {
	Path string
	Key  string
}

UnknownFieldError is returned in obstructed mode when a JSON key does not match any struct field.

func (UnknownFieldError) Error

func (e UnknownFieldError) Error() string

type UnmarshalErrors

type UnmarshalErrors struct {
	Errors []error
}

UnmarshalErrors collects multiple non-fatal errors from a single Unmarshal operation (e.g., multiple Const[T] mismatches).

func (UnmarshalErrors) Error

func (e UnmarshalErrors) Error() string

func (UnmarshalErrors) Unwrap

func (e UnmarshalErrors) Unwrap() []error

type Unmarshaler

type Unmarshaler interface {
	UnmarshalJSON([]byte) error
}

Unmarshaler is something that can unmarshal itself from JSON.

type Usher

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

Usher marshals a Go type into JSON.

If you want the "string" modifier you will need to call json.Usher.ImplantModifier() to add it:

var jsonUsher json.Usher

jsonUsher.ImplantModifier("string", json.StringModifierFunc, json.BareModifierFunc)

(Note that BareModifierFunc is also included because it is the inverse-operation to StringModifierFunc.)

You can also add your own modifiers:

var jsonUsher json.Usher

jsonUsher.ImplantModifier("digest", digestFunc, nil)
var (
	// DefaultUsher is the Usher that the json.Marshal() function uses.
	//
	// Implanting a modifier into DefaultUsher into DefaultUsher modifies how the json.Marshal() behaves.
	DefaultUsher Usher
)

func (*Usher) ImplantModifier

func (receiver *Usher) ImplantModifier(name string, marshalFn ModifierFunc, unmarshalFn ModifierFunc)

func (*Usher) Marshal

func (receiver *Usher) Marshal(value any) ([]byte, error)

Marshal returns the JSON version of 'value'.

omitempty

For Go structs, if a field in the struct includes the struct-tag `omitempty`, then — Marshal will NOT include its in the resulting JSON if its Go value is empty.

For example, consider:

type MyStruct struct {
	Once   string
	Twice  string `json:"twice,omitempty"` // <---------
	Thrice string `json:"thrice"`
	Fource string `json:",omitempty"`      // <---------
}

Note that field `Twice` and field `Fource` both have `omitempty` in their struct-tags. So, if their values are empty, then the resulting JSON will omit them.

For example, this:

var value MyStruct

Would (conceptually) result in:

{
	"Once":   "",
	"thrice": ""
}

And, for example, this:

var value = MyStruct{
	Once:   "",
	Twice:  "",
	Thrice: "",
	Fource: ""
}

Would also (conceptually) result in:

{
	"Once":   "",
	"thrice": ""
}

And also, for example, this:

var value = MyStruct{
	Once:   "first",
	Twice:  "second",
	Thrice: "third",
	Fource: "fourth"
}

Would (conceptually) result in:

{
	"Once":   "first",
	"twice":  "second",
	"thrice": "third",
	"Fource": "forth"
}

Custom types can also make use of Emptier or Nothinger to specify when they are empty. For example:

type MyStruct struct {
	// ...
}

func (receiver MyStruct) IsEmpty() bool {
	// ...
}

Marshal will call IsEmpty, if a custom type has it, to check whether the custom type is `empty` or not, for the purposes of `omitempty`.

func (*Usher) MergeAndMarshal

func (receiver *Usher) MergeAndMarshal(values ...any) ([]byte, error)

func (*Usher) ObstructedUnmarshal

func (receiver *Usher) ObstructedUnmarshal(data []byte, dst any) error

ObstructedUnmarshal deserializes JSON data strictly. Returns an error if unknown JSON fields are encountered.

func (*Usher) Unmarshal

func (receiver *Usher) Unmarshal(data []byte, dst any) error

Unmarshal deserializes JSON data into the value pointed to by dst. Unknown JSON fields are silently ignored.

func (*Usher) UnobstructedUnmarshal

func (receiver *Usher) UnobstructedUnmarshal(data []byte, dst any) error

UnobstructedUnmarshal deserializes JSON data permissively. Allows trailing commas, comments, and leading plus-signs. Unknown JSON fields are silently ignored.

Jump to

Keyboard shortcuts

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