Documentation
¶
Overview ¶
Package jp provides fast JSON parsing, querying, patching, and structural comparison. It offers two complementary APIs:
Streaming parser: Fast, zero-allocation operations on raw []byte JSON without unmarshaling. Core functions: Get, GetString, GetInt, GetBoolean, ArrayEach, ObjectEach. Returns slices of the input buffer - no allocation when reading.
Index: A flat-buffer structure that encodes the full parse tree as integer-offset nodes. Supports O(log n) key lookups via binary search, mutation via copy-on-write, and zero-copy transport via IndexBytes/OpenIndex.
Both APIs avoid type conversions by default (everything is []byte with a ValueType marker), making them ideal for high-performance JSON manipulation without marshaling overhead.
Example: Streaming Parser ¶
jp.Get(data, "person", "name", "fullName") jp.GetInt(data, "person", "github", "followers") jp.ArrayEach(data, callback, "person", "avatars")
Example: Index with Mutation ¶
idx, _ := jp.MakeIndex(data)
idx.Delete("person", "github")
idx.Add(`{"handle":"rackn"}`, "person", "gitlab")
data, _ := idx.MarshalJSON()
Index Buffer Format ¶
The Index type supports serialization via IndexBytes and reconstruction via OpenIndex. The on-disk format (v5/v6) uses variable-width encoding to minimize memory footprint: uint8, uint16, or uint32 offsets depending on container size. Compact() rebuilds a fresh index with optimal encoding and only live nodes.
Index ¶
- Constants
- Variables
- func ArrayEach(data []byte, ...) error
- func Equal(a, b []byte) bool
- func GetBigInt(data []byte, keys ...string) (*big.Int, error)
- func GetBoolean(data []byte, keys ...string) (val bool, err error)
- func GetFloat(data []byte, keys ...string) (val float64, err error)
- func GetInt(data []byte, keys ...string) (val int64, err error)
- func GetNull(data []byte, keys ...string) error
- func GetString(data []byte, keys ...string) (val string, err error)
- func IsNull(b []byte) bool
- func ObjectEach(data []byte, callback func(key []byte, value []byte, dataType ValueType) error, ...) (err error)
- func ParseBigInt(b []byte) (res *big.Int, err error)
- func ParseBoolean(b []byte) (bool, error)
- func ParseFloat(b []byte) (float64, error)
- func ParseInt(b []byte) (int64, error)
- func ParseString(b []byte) (string, error)
- func Unescape(in, out []byte) ([]byte, error)
- type Cursor
- func (c *Cursor) All() iter.Seq2[string, *Index]
- func (c *Cursor) Ascend(n int) (int, bool)
- func (c *Cursor) Descend(keys ...string) (int, bool)
- func (c *Cursor) Down() bool
- func (c *Cursor) First() bool
- func (c *Cursor) Item() (string, *Index)
- func (c *Cursor) KeyBytes() []byte
- func (c *Cursor) Last() bool
- func (c *Cursor) Len() int
- func (c *Cursor) Next() bool
- func (c *Cursor) Pos() int
- func (c *Cursor) Prev() bool
- func (c *Cursor) Seek(k string) bool
- func (c *Cursor) Self() *Index
- func (c *Cursor) Up() bool
- type Index
- func (ib *Index) Add(value []byte, keys ...string) error
- func (ib *Index) AppendJSON(buf []byte) ([]byte, error)
- func (ib *Index) BigInt() (*big.Int, error)
- func (ib *Index) Bool() (bool, error)
- func (ib *Index) Compact() *Index
- func (ib *Index) Cursor() *Cursor
- func (ib *Index) Delete(keys ...string) error
- func (ib *Index) Equal(other *Index) bool
- func (ib *Index) Float() (float64, error)
- func (ib *Index) Get(keys ...string) (*Index, error)
- func (ib *Index) GetBigInt(keys ...string) (*big.Int, error)
- func (ib *Index) GetBoolean(keys ...string) (val bool, err error)
- func (ib *Index) GetFloat(keys ...string) (val float64, err error)
- func (ib *Index) GetInt(keys ...string) (val int64, err error)
- func (ib *Index) GetInto(dst *Index, keys ...string) error
- func (ib *Index) GetNull(keys ...string) error
- func (ib *Index) GetString(keys ...string) (val string, err error)
- func (ib *Index) IndexBytes() []byte
- func (ib *Index) Int() (int64, error)
- func (ib *Index) Len() int
- func (i *Index) Make(j []byte) error
- func (ib *Index) MarshalJSON() ([]byte, error)
- func (ib *Index) Null() error
- func (i *Index) Open(json, idxBuf []byte) error
- func (ib *Index) Replace(value []byte, keys ...string) error
- func (ib *Index) Rewrite() (*Index, error)
- func (ib *Index) String() (string, error)
- func (ib *Index) Type() ValueType
- func (ib *Index) WriteTo(w io.Writer) (int64, error)
- type Op
- type Patch
- type PatchOpts
- type Patcher
- func (p *Patcher) Add(path Pointer, value any)
- func (p *Patcher) Append(other Patch)
- func (p *Patcher) Copy(path, from Pointer)
- func (p *Patcher) Missing(path Pointer)
- func (p *Patcher) Move(path, from Pointer)
- func (p *Patcher) Op(op string, path, from Pointer, value any)
- func (p *Patcher) Patch() (Patch, error)
- func (p *Patcher) Remove(path Pointer)
- func (p *Patcher) Replace(path Pointer, value any)
- func (p *Patcher) Test(path Pointer, val any)
- type Pointer
- func (p Pointer) Append(frag string) Pointer
- func (p Pointer) Chop() (string, Pointer)
- func (p Pointer) Contains(q Pointer) bool
- func (p Pointer) Equal(other Pointer) bool
- func (p Pointer) MarshalJSON() ([]byte, error)
- func (p Pointer) Path() []string
- func (p Pointer) Shift() (string, Pointer)
- func (p Pointer) String() string
- func (p *Pointer) UnmarshalJSON(buf []byte) error
- func (p Pointer) Valid() bool
- type ValueType
Constants ¶
const ( // NotExist indicates that the requested key path was not found. NotExist = ValueType(iota) // String is a JSON string value. String // Number is a JSON number value. Number // Object is a JSON object value. Object // Array is a JSON array value. Array // Boolean is a JSON boolean value (true or false). Boolean // Null is a JSON null literal. Null // Unknown is returned when the value type cannot be determined. Unknown = ValueType(255) )
const ContentType = "application/json-patch+json"
ContentType is the MIME type for JSON Patch documents (RFC 6902).
const MaxKeyLen = 16 * 1024
MaxKeyLen is the maximum byte length of an object key. Object key lengths are stored as uint16 in the index buffer, so keys longer than MaxKeyLen would be silently truncated; instead, the library rejects them with KeyTooLongError.
Variables ¶
var ( // StopIteration is returned from an [ObjectEach] callback to terminate iteration early. StopIteration = errors.New("stop iteration") // KeyPathNotFoundError is returned when a key path does not resolve to a value. KeyPathNotFoundError = errors.New("Key path not found") // KeyPathFoundError is returned by the "missing" patch op when the path unexpectedly exists. KeyPathFoundError = errors.New("Key path exists") // UnknownValueTypeError is returned when a JSON value cannot be classified. UnknownValueTypeError = errors.New("Unknown value type") // MalformedJsonError is returned when the input is not valid JSON. MalformedJsonError = errors.New("Malformed JSON error") // MalformedStringError is returned when a JSON string is missing its closing quote. MalformedStringError = errors.New("Value is string, but can't find closing '\"' symbol") // MalformedArrayError is returned when a JSON array is missing its closing bracket. MalformedArrayError = errors.New("Value is array, but can't find closing ']' symbol") // MalformedObjectError is returned when a JSON object is missing its closing brace. MalformedObjectError = errors.New("Value looks like object, but can't find closing '}' symbol") // MalformedValueError is returned when a JSON value has no recognizable terminator. MalformedValueError = errors.New("Value looks like Number/Boolean/None, but can't find its end: ',' or '}' symbol") // OverflowIntegerError is returned when an integer value exceeds int64 range. OverflowIntegerError = errors.New("Value is number, but overflowed while parsing") // MalformedNumberError is returned when a number has invalid syntax. MalformedNumberError = errors.New("Value is number, but starts '0' or '-0' or is an invalid float") // MalformedStringEscapeError is returned when a string contains an invalid escape sequence. MalformedStringEscapeError = errors.New("Encountered an invalid escape sequence in a string") // NotStringError is returned when a value was expected to be a string but is not. NotStringError = errors.New("Value is not a string") // NotFloatError is returned when a value was expected to be a float but is not. NotFloatError = errors.New("Value is not a float") // NotIntegerError is returned when a value was expected to be an integer but is not. NotIntegerError = errors.New("Value is not an integer") // NotBooleanError is returned when a value was expected to be a boolean but is not. NotBooleanError = errors.New("Value is not a boolean") // NotNullError is returned when a value was expected to be null but is not. NotNullError = errors.New("Value is not null") // NotEqualError is returned when a JSON Patch "test" op finds unequal values. NotEqualError = errors.New("Values are not equal") // BadMoveError is returned when a JSON Patch "move" op would move a value into itself. BadMoveError = errors.New("Cannot move a value into itself") // BadPatchOpError is returned when a patch operation is invalid or unrecognized. BadPatchOpError = errors.New("Invalid patch Op") // NotArrayError is returned when a value was expected to be an array but is not. NotArrayError = errors.New("Value is not an array") // NotObjectError is returned when a value was expected to be an object but is not. NotObjectError = errors.New("Value is not an object") // IndexVersionError is returned by [OpenIndex] when the buffer format version is unrecognized. IndexVersionError = errors.New("Index buffer format version not recognized") // KeyTooLongError is returned when an object key exceeds [MaxKeyLen] bytes. KeyTooLongError = errors.New("object key exceeds maximum length") )
Sentinel errors returned by parsing, querying, and patching operations.
var ( // ErrMissingOp indicates that a patch operation is missing its "op" field. ErrMissingOp = errors.New("missing op") // ErrMissingPath indicates that a patch operation is missing its "path" field. ErrMissingPath = errors.New("missing path") )
var IllegalPointerError = fmt.Errorf("illegal pointer")
IllegalPointerError is returned when a string is not a valid JSON Pointer.
Functions ¶
func ArrayEach ¶
func ArrayEach(data []byte, cb func(value []byte, dataType ValueType, offset int, err error) error, keys ...string) error
ArrayEach iterates over the elements of a JSON array, invoking cb for each element. The optional keys traverse to a nested array before iterating. Return StopIteration from the callback to stop iteration early.
Callback signature: func(value []byte, dataType ValueType, offset int, err error) error
func Equal ¶
Equal reports whether the JSON documents a and b are structurally equal. It first compares the raw bytes directly. If they differ, it parses both into an Index and performs a deep structural comparison.
func GetBigInt ¶ added in v0.9.5
GetBigInt returns the big.Int value at the given key path. It returns an error if the key path is not found or the value is not a number. Use this when GetInt returns OverflowIntegerError.
func GetBoolean ¶
GetBoolean returns the bool value at the given key path. It returns an error if the key path is not found or the value is not a boolean.
func GetFloat ¶
GetFloat returns the float64 value at the given key path. It returns an error if the key path is not found or the value is not a number.
func GetInt ¶
GetInt returns the int64 value at the given key path. It returns an error if the key path is not found or the value is not a number.
func GetString ¶
GetString returns the string value at the given key path, handling JSON unescaping and UTF-8 decoding. It returns an error if the key path is not found or the value is not a string.
func ObjectEach ¶
func ObjectEach(data []byte, callback func(key []byte, value []byte, dataType ValueType) error, keys ...string) (err error)
ObjectEach iterates over the key-value pairs of a JSON object, invoking callback for each entry. The optional keys traverse to a nested object before iterating. Return StopIteration from the callback to stop early.
Callback signature: func(key []byte, value []byte, dataType ValueType) error
func ParseBigInt ¶ added in v0.9.5
ParseBigInt parses a JSON integer of arbitrary size into a big.Int. Use this when ParseInt returns OverflowIntegerError.
func ParseBoolean ¶
ParseBoolean parses a JSON boolean literal into a Go bool.
func ParseFloat ¶
ParseFloat parses a JSON number value into a Go float64.
func ParseString ¶
ParseString parses a JSON string value (including surrounding quotes) into a Go string, unescaping any JSON escape sequences.
func Unescape ¶
Unescape unescapes the string contained in 'in' and returns it as a slice. If 'in' contains no escaped characters:
Returns 'in'.
Else, if 'out' is of sufficient capacity (guaranteed if cap(out) >= len(in)):
'out' is used to build the unescaped string and is returned with no extra allocation
Else:
A new slice is allocated and returned.
Types ¶
type Cursor ¶ added in v0.10.0
type Cursor struct {
// contains filtered or unexported fields
}
Cursor provides stack-based, allocation-free navigation through a JSON tree. It is created via (*Index).Cursor and shares the underlying json/idx buffers.
Cursor uses stack-allocated memory for depths ≤ 8, avoiding heap allocations. The returned *Index from Item() and Self() is valid only until the next Cursor method call.
Use an iterator to traverse all children:
for key, child := range c.All() {
fmt.Printf("%s: %s\n", key, string(child.MarshalJSON()))
}
func (*Cursor) All ¶ added in v0.10.0
All returns an iterator over the direct children of this Cursor starting at the current cursor position.
For objects, keys are field names in sorted order For arrays, keys are decimal indices. For anything else, key will be an empty string.
IMPORTANT: The iterator owns the *Index that is returned. If you need to save it to do eomthing with it, make a deep copy of it with: myCopy := *value
func (*Cursor) Ascend ¶ added in v0.10.0
Ascend pops n levels up the cursor stack by calling Up repeatedly. It returns the number of levels actually ascended and true if all n Up calls succeeded. If the cursor reaches the root before n levels have been popped, it returns the count reached so far and false.
func (*Cursor) Descend ¶ added in v0.10.0
Descend navigates from the current position to the nested value identified by the key path keys. For each key except the last it calls Seek then Down to step inside that container. For the final key it calls Seek only, leaving the cursor positioned at that key within its parent container.
After a successful Descend, call Item to read the value, Down to enter it (if it is a container), or All to iterate its children.
Descend returns the index of the last key it attempted and true if every key was found. On failure the index identifies the missing key.
func (*Cursor) Down ¶ added in v0.10.0
Down descends into the container child at the current position. The cursor is positioned at the first item of that container. Returns false if the child is a simple value (not a container).
func (*Cursor) First ¶ added in v0.10.0
First moves to the first position. Returns false if the container is empty.
func (*Cursor) Item ¶ added in v0.10.0
Item returns the key and value at the current position.
For objects the key is the field name; for arrays it is the decimal index. For a simple-value cursor (no container) the key is "".
The returned *Index is reused across calls — it is only valid until the next Cursor method call.
func (*Cursor) KeyBytes ¶ added in v0.10.0
KeyBytes returns the raw (unescaped) key bytes for the current object entry. Returns nil if the current container is an array. The returned slice is valid until the next Cursor method call.
func (*Cursor) Last ¶ added in v0.10.0
Last moves to the last position. Returns false if the container is empty.
func (*Cursor) Len ¶ added in v0.10.0
Len returns the number of children in the current container, or 0 for a simple-value cursor or an empty container.
func (*Cursor) Next ¶ added in v0.10.0
Next moves to the next sibling. Returns false if already at the last position.
func (*Cursor) Pos ¶ added in v0.10.0
Pos returns the current zero-based position within the container.
func (*Cursor) Prev ¶ added in v0.10.0
Prev moves to the previous sibling. Returns false if already at the first position.
func (*Cursor) Seek ¶ added in v0.10.0
Seek moves to the position of key k in the current container.
For objects, it binary-searches the sorted entries and positions the cursor at k (returning true) or at the insertion point (returning false).
For arrays, k is parsed as an integer index in either bare ("3") or bracketed ("[3]") form. Negative indices count from the end (-1 or [-1] is the last element). Returns true and positions the cursor if the index is valid; returns false without moving if k is not a valid index or is out of bounds.
func (*Cursor) Self ¶ added in v0.10.0
Self returns an Index for the container the cursor is currently working in. It is the direct equivalent of building an Index from the cursor's json/idx buffers and the current container offset.
The returned *Index is reused across calls — it is only valid until the next Cursor method call.
type Index ¶
type Index struct {
// contains filtered or unexported fields
}
Index encodes a complete JSON parse tree as integer-offset nodes inside a flat byte slice (idx), paired with the original JSON buffer. An Index supports O(log n) key lookups, structural equality, mutation via copy-on-write, and zero-copy transport via [IndexBytes] / OpenIndex.
The Index type is safe for concurrent use by multiple goroutines when each goroutine operates on a distinct Index value. Methods that modify the receiver (Add, Replace, Delete, Compact) are not safe for concurrent use on the same value; these operations use copy-on-write internally but the receiver itself is mutated. For concurrent access to the same logical document, create distinct Index values via MarshalJSON/OpenIndex or use external synchronization.
func IndexValue ¶
IndexValue creates an Index for the first JSON value in buf. If IndexValue returns without an error, then idx points to the first position in buf after the JSON value that was parsed.
If IndexValue returns with an error, idx points to the start of the JSON value that caused the parse error.
func MakeIndex ¶
MakeIndex parses json into an Index, appending index nodes into idx. Pass nil (or an empty slice) to let MakeIndex allocate. Pass a pre-allocated slice to avoid a heap allocation — the caller retains ownership of the backing array. Unlike Index.Make, MakeIndex does not reset idx: it appends the new index after any existing content, preserving bytes already in the slice. This matters when the caller passes a non-empty buffer whose backing array must not be overwritten (e.g. Patch.Apply passing the previous result as scratch). The first 2 bytes of the appended index contain the format version.
func OpenIndex ¶ added in v0.10.0
OpenIndex reconstructs an Index from a JSON buffer and an index buffer previously produced by IndexBytes. The root node offset is read from the last 4 bytes of idx.
Versions 2, 3, 5, and 6 are loaded directly from the buffer. Version 4 stored narrow container offsets as absolute values, which is incompatible with the relative encoding used by v5+; any other unrecognized version may also be structurally incompatible. For these cases OpenIndex transparently rebuilds the index by re-parsing json — the idx buffer is reused as scratch space for the rebuild (equivalent to MakeIndex(json, idx[:0])), so callers can pass a pre-allocated buffer to avoid allocation on the rebuild path. The only errors returned are JSON parse errors from the rebuild path.
func (*Index) Add ¶
Add inserts the JSON in value at the given key path. For arrays, the special key "-" appends to the end. For objects, it inserts at the sorted position (maintaining lexicographic key order). Returns KeyPathNotFoundError if the parent container does not exist, KeyTooLongError if the key exceeds MaxKeyLen.
func (*Index) AppendJSON ¶ added in v0.10.0
AppendJSON appends the serialized JSON for this node to buf and returns the extended buffer. Unlike MarshalJSON it lets the caller provide (and reuse) the output buffer, avoiding a bytes.Buffer heap allocation.
func (*Index) BigInt ¶ added in v0.10.0
BigInt returns the *big.Int value of this Index. It returns an error if the current node is not a number. Use this when Int() returns OverflowIntegerError.
func (*Index) Bool ¶ added in v0.10.0
Bool returns the bool value of this Index. It returns an error if the current node is not a boolean.
func (*Index) Compact ¶ added in v0.10.0
Compact returns a new Index with freshly serialized JSON and a freshly built index buffer derived from the current state of this Index. The result is fully self-contained with no dependency on the receiver's JSON buffer. The modified flag is cleared in the returned Index.
func (*Index) Cursor ¶ added in v0.10.0
Cursor returns a Cursor for navigating the children of this Index node.
For container roots (array/object), the cursor starts at position 0. For simple roots (string/number/bool/null), only Item() is useful — it returns ("", value). All navigation methods return false.
func (*Index) Float ¶ added in v0.10.0
Float returns the float64 value of this Index. It returns an error if the current node is not a number.
func (*Index) Get ¶
Get returns a new Index for the value at the given key path. The returned Index shares the underlying json and idx buffers with the receiver; the receiver must remain valid for the lifetime of the returned Index.
For allocation-free lookups, see Index.GetInto.
func (*Index) GetBigInt ¶ added in v0.10.0
GetBigInt is like Index.Get but returns the *big.Int value directly. Use this when GetInt returns OverflowIntegerError.
func (*Index) GetBoolean ¶ added in v0.10.0
GetBoolean is like Index.Get but returns the bool value directly. It returns an error if the key path is not found or the value is not a boolean.
func (*Index) GetFloat ¶ added in v0.10.0
GetFloat is like Index.Get but returns the float64 value directly. It returns an error if the key path is not found or the value is not a number.
func (*Index) GetInt ¶ added in v0.10.0
GetInt is like Index.Get but returns the int64 value directly. It returns an error if the key path is not found or the value is not a number or if the value overflows int64.
func (*Index) GetInto ¶ added in v0.10.0
GetInto is like Get but writes the result into dst instead of allocating a new Index on the heap. This avoids one allocation per call when the caller can supply a stack-local or reusable Index. The dst.Index shares the underlying buffers with the receiver.
func (*Index) GetNull ¶ added in v0.10.0
GetNull is like Index.Get but returns an error if the value at the key path is not null.
func (*Index) GetString ¶ added in v0.10.0
GetString is like Index.Get but returns the string value directly, handling JSON unescaping. It returns an error if the key path is not found or the value is not a string.
func (*Index) IndexBytes ¶ added in v0.10.0
IndexBytes returns the index buffer with the root node offset appended as the final 4 bytes (little-endian). Pass this, together with the original JSON, to OpenIndex to reconstruct the Index without re-parsing.
func (*Index) Int ¶ added in v0.10.0
Int returns the int64 value of this Index. It returns an error if the current node is not a number or if the value overflows int64.
func (*Index) Len ¶ added in v0.10.0
Len returns the serialized JSON byte length of this node in O(1). If the Index is empty, returns 0.
func (*Index) Make ¶ added in v0.10.0
Make parses j and builds the index into the receiver. If i.idx is already allocated its length is reset to zero before building, so the index occupies the buffer from the start; otherwise a fresh buffer is allocated. Callers that already hold an *Index (e.g. a stack-local or pool-recycled value) can avoid a heap allocation by calling Make directly instead of MakeIndex. Unlike MakeIndex, Make always resets i.idx before writing — do not use Make when the backing array of i.idx must not be overwritten. On success, modified is set to false. On error the receiver is left in an indeterminate state and should not be used.
func (*Index) MarshalJSON ¶
MarshalJSON implements encoding/json.Marshaler. For allocation-free serialization, see Index.AppendJSON.
func (*Index) Null ¶ added in v0.10.0
Null returns an error if the current node is not a null value.
func (*Index) Open ¶ added in v0.10.0
Open loads an index from a previously serialized buffer into the receiver, or rebuilds it from json if the buffer version is unrecognized. It is the in-place equivalent of OpenIndex: callers that already hold an *Index can avoid a heap allocation by calling Open directly. Versions 2, 3, and 5 are accepted directly; any other version triggers a transparent rebuild via [Make]. On success, modified is set to false.
func (*Index) Replace ¶
Replace replaces the value at the given key path with the JSON in value. It returns KeyPathNotFoundError if the path does not exist. The operation uses copy-on-write semantics: the receiver is mutated, but the original JSON buffer is not modified.
func (*Index) Rewrite ¶ added in v0.10.0
Rewrite returns a new Index with freshly serialized JSON and a freshly built index buffer derived from the current state of this Index. Unlike [Compact] which allocates with make([]byte, 0, ib.Len()), Rewrite accepts an optional pre-allocated output buffer. Returns the new Index or an error if JSON serialization fails.
func (*Index) String ¶ added in v0.10.0
String returns the string value of this Index. It returns an error if the current node is not a string.
type Op ¶ added in v0.9.3
type Op []byte
Op represents a single JSON Patch operation as defined by RFC 6902. It is the raw JSON bytes of one operation object. Supported operations:
"add" - Add a value at the given path "remove" - Remove the value at the given path "replace"- Replace the value at the given path "move" - Move a value from one path to another "copy" - Copy a value from one path to another "test" - Test that the value at a path matches a given value "missing"- Non-standard: fail if the path exists (for idempotent ops)
The "missing" op is a non-standard extension that returns KeyPathFoundError if the path exists, and succeeds if the path is absent.
func (Op) From ¶ added in v0.9.3
From returns the "from" field as a Pointer, or nil if the field is absent. Only "move" and "copy" operations use this field.
func (Op) Op ¶ added in v0.9.3
Op returns the "op" field of this operation. It panics if the field is missing.
func (Op) Path ¶ added in v0.9.3
Path returns the "path" field as a Pointer. It panics if the field is missing or is not a well-formed JSON Pointer.
func (Op) Valid ¶ added in v0.9.3
Valid reports whether the operation has all required fields and valid values. It checks that the "op" field is present and recognized, the "path" field is a valid JSON Pointer, and any required fields (value for "add"/"replace"/"test", from for "move"/"copy") are present and well-formed.
func (Op) Value ¶ added in v0.9.3
func (o Op) Value() json.RawMessage
Value returns the raw JSON "value" field of this operation, or nil if absent. The returned value is of type json.RawMessage (a []byte alias) and must not be modified.
type Patch ¶
type Patch []byte
Patch is a JSON Patch document (RFC 6902) stored as raw JSON bytes. In addition to the standard operations, it supports a non-standard "missing" operation that fails if the specified path already exists, enabling truly atomic guard semantics for additions.
func Generate ¶
Generate generates a JSON Patch that transforms base into target. If paranoid is true, each mutation op is preceded by a "test" op that verifies the old value before applying the change. Both base and target must be valid JSON. Returns a complete RFC 6902 JSON Patch document.
func GenerateFull ¶
GenerateFull generates a JSON Patch that transforms base into target. If paranoid is true, each mutation op is preceded by a per-field "test" op. If pretest is true, a single "test" op for the entire base document is prepended instead (overriding paranoid). Both base and target must be valid JSON. Returns a complete RFC 6902 JSON Patch document.
func MakePatch ¶ added in v0.9.2
MakePatch generates a JSON Patch that transforms base into target, controlled by opts. Both base and target must be valid JSON.
func (Patch) Apply ¶
Apply applies the patch to base, which must be valid JSON. It returns the resulting JSON, any error, and the zero-based index of the failing Op (or 0 on success). The buf parameter is used as scratch space for index construction; callers can pass the previous result back as buf to amortize allocation costs across calls. The returned result never aliases buf, so it is safe to retain across multiple calls.
func (Patch) MarshalJSON ¶ added in v0.9.3
MarshalJSON implements encoding/json.Marshaler.
func (Patch) Ops ¶ added in v0.9.3
Ops returns the individual patch operations, primarily for debugging.
func (*Patch) UnmarshalJSON ¶ added in v0.9.3
UnmarshalJSON implements encoding/json.Unmarshaler.
type PatchOpts ¶ added in v0.9.2
type PatchOpts struct {
// TestIndividualChanges adds a "test" op before every "remove" or
// "replace" op, verifying the old value before mutating it. "add"
// ops for new object fields do not receive a "test" because the
// field does not yet exist; use SupportMissingOp for that case.
TestIndividualChanges bool
// SupportMissingOp emits a non-standard "missing" op before "add"
// ops on new fields. The "missing" op passes only if the path does
// not exist, providing truly atomic guard semantics for additions.
SupportMissingOp bool
// TestFullBase prepends a single "test" op that asserts the entire
// base document, disabling all per-field tests. Use this only when
// you want to guard the full object rather than individual changes,
// as the resulting patch may reject any concurrent modification.
TestFullBase bool
}
PatchOpts controls how MakePatch generates a JSON Patch.
type Patcher ¶ added in v0.9.3
type Patcher struct {
// contains filtered or unexported fields
}
Patcher builds a JSON Patch programmatically by accumulating operations. A zero-value Patcher is ready for use.
func (*Patcher) Append ¶ added in v0.9.3
Append copies all operations from other into the patch being built.
func (*Patcher) Copy ¶ added in v0.9.3
Copy appends a "copy" operation that duplicates the value from from to path.
func (*Patcher) Missing ¶ added in v0.9.3
Missing appends a non-standard "missing" operation that passes only if the given path does not exist.
func (*Patcher) Move ¶ added in v0.9.3
Move appends a "move" operation that relocates the value from from to path.
func (*Patcher) Op ¶ added in v0.9.3
Op appends a single operation to the patch being built. The value parameter may be an *Index, encoding/json.RawMessage, encoding/json.Marshaler, or any value accepted by encoding/json.Marshal.
func (*Patcher) Patch ¶ added in v0.9.3
Patch finalizes the accumulated operations and returns the resulting Patch. If any operation recorded an error, or the resulting JSON is invalid, an error is returned along with the raw bytes for diagnostics. After Patch returns the Patcher is reset and ready for reuse.
func (*Patcher) Remove ¶ added in v0.9.3
Remove appends a "remove" operation that deletes the value at path.
type Pointer ¶
type Pointer []byte
Pointer is a JSON Pointer (RFC 6901) stored as a byte slice. It extends the standard with negative array indices that count from the end.
Example usage:
Ptr("/users/-1/name") // Last user's name
Ptr("/users/0") // First user
PtrTo("users", "-1", "name") // Same as Ptr("/users/-1/name")
Pointer values are safe for concurrent use by multiple goroutines when each goroutine operates on a distinct Pointer value.
func NewPointer ¶
NewPointer parses s as an RFC 6901 JSON Pointer. It returns an error if s is not a valid pointer.
func Ptr ¶ added in v0.9.3
Ptr is like NewPointer but panics on an invalid pointer string.
func PtrTo ¶ added in v0.9.3
PtrTo constructs a Pointer from the given path fragments. It is the inverse of Pointer.String. Each fragment is JSON-Pointer-escaped internally. For negative array indices, use the string "-1", "-2", etc.
func (Pointer) Append ¶
Append returns a new Pointer with frag appended as an additional path segment.
func (Pointer) Chop ¶ added in v0.9.1
Chop removes and returns the last path segment and the remaining pointer.
func (Pointer) Contains ¶
Contains reports whether q refers to a value contained within p. For example, ["/users/0"] contains ["/users/0/name"].
func (Pointer) MarshalJSON ¶
MarshalJSON implements encoding/json.Marshaler.
func (Pointer) Path ¶
Path splits the pointer into decoded path segments suitable for use as the keys arguments accepted by Get, Index.Get, and similar functions.
func (Pointer) Shift ¶ added in v0.9.1
Shift removes and returns the first path segment and the remaining pointer.
func (*Pointer) UnmarshalJSON ¶
UnmarshalJSON implements encoding/json.Unmarshaler.
type ValueType ¶
type ValueType byte
ValueType identifies the JSON type of a parsed value.
func Get ¶
Get extracts a value from the raw JSON in data at the given key path.
Multiple keys may be provided to traverse nested structures (e.g. Get(data, "user", "name")). If no keys are given, Get returns the first complete JSON value in data.
It returns the raw bytes of the value, its ValueType, the byte offset past the value in data, and any error. If the key path is not found, dataType is NotExist and err is KeyPathNotFoundError.
The returned []byte slices point into the input data buffer and must not be modified. They are valid only as long as the data buffer remains unchanged.