@@ -6,42 +6,81 @@ Go implementation of [JSON Pointer (RFC 6901)](https://datatracker.ietf.org/doc/
66and mutating JSON documents represented as Go values. Works with ` map[string]any ` , slices, and Go structs
77(resolved via ` json ` struct tags and reflection).
88
9- ## Package Layout (single package)
9+ ## Package Layout
10+
11+ Two packages in one module (` github.com/go-openapi/jsonpointer ` ):
1012
1113| File | Contents |
1214| ------| ----------|
13- | ` pointer.go ` | Core types (` Pointer ` , ` JSONPointable ` , ` JSONSetable ` ), ` New ` , ` Get ` , ` Set ` , ` Offset ` , ` Escape ` /` Unescape ` |
14- | ` errors.go ` | Sentinel errors: ` ErrPointer ` , ` ErrInvalidStart ` , ` ErrUnsupportedValueType ` |
15+ | ` pointer.go ` | ` Pointer ` , ` New ` , ` Get ` , ` Set ` , ` Offset ` , ` GetForToken ` , ` SetForToken ` , ` Escape ` /` Unescape ` , and the reflection helpers |
16+ | ` ifaces.go ` | ` JSONPointable ` , ` JSONSetable ` , ` NameProvider ` interfaces |
17+ | ` options.go ` | ` Option ` , ` WithNameProvider ` , ` SetDefaultNameProvider ` , ` UseGoNameProvider ` , ` DefaultNameProvider ` |
18+ | ` errors.go ` | Sentinel errors and their constructors |
19+ | ` jsonname/name_provider.go ` | ` NameProvider ` — the default, tag-only resolver (` DefaultJSONNameProvider ` ) |
20+ | ` jsonname/go_name_provider.go ` | ` GoNameProvider ` — the alternative resolver, follows ` encoding/json ` rules |
1521
1622## Key API
1723
1824- ` New(string) (Pointer, error) ` — parse a JSON pointer string (e.g. ` "/foo/0/bar" ` )
19- - ` Pointer.Get(document any) (any, reflect.Kind, error) ` — retrieve a value
20- - ` Pointer.Set(document, value any) (any, error) ` — set a value (document must be pointer/ map/ slice)
25+ - ` Pointer.Get(document any, opts ...Option ) (any, reflect.Kind, error) ` — retrieve a value
26+ - ` Pointer.Set(document, value any, opts ...Option ) (any, error) ` — set a value (document must be a pointer, map or slice)
2127- ` Pointer.Offset(jsonString string) (int64, error) ` — byte offset of token in raw JSON
2228- ` GetForToken ` / ` SetForToken ` — single-level convenience helpers
2329- ` Escape ` / ` Unescape ` — RFC 6901 token escaping (` ~0 ` ↔ ` ~ ` , ` ~1 ` ↔ ` / ` )
2430
2531Custom types can implement ` JSONPointable ` (for Get) or ` JSONSetable ` (for Set) to bypass reflection.
2632
33+ Sentinel errors: ` ErrPointer ` , ` ErrInvalidStart ` , ` ErrUnsupportedValueType ` , ` ErrDashToken ` .
34+ Errors raised by the package wrap ` ErrPointer ` . Errors returned by a caller's ` JSONLookup ` or
35+ ` JSONSet ` are passed through unchanged, so ` errors.Is(err, ErrPointer) ` is false for those.
36+
37+ ## Name providers
38+
39+ Two implementations of the ` NameProvider ` interface resolve go field names to json names. The
40+ difference drives most "why is my field unreachable" questions:
41+
42+ - ` jsonname.NameProvider ` (the default, ` jsonname.DefaultJSONNameProvider ` ): only fields carrying a
43+ non-empty ` json ` tag are reachable.
44+ - ` jsonname.GoNameProvider ` (opt in with ` UseGoNameProvider() ` or ` WithNameProvider ` ): follows
45+ ` encoding/json ` , so untagged exported fields are reachable under their go name.
46+
2747## Design Decisions
2848
29- - Struct fields ** must** have a ` json ` tag to be reachable; untagged fields are ignored.
30- - Anonymous embedded struct fields are traversed only if tagged.
31- - The RFC 6901 ` "-" ` array suffix (append) is ** not** implemented.
49+ - Under the default provider, struct fields ** must** have a ` json ` tag to be reachable; untagged
50+ fields are ignored. Use ` UseGoNameProvider() ` for ` encoding/json ` semantics.
51+ - An anonymous (embedded) field is walked for the fields it promotes, and its own ` json ` tag is
52+ ignored — tagged or not, the tag never becomes a reachable key.
53+ - Embedding is traversed through a pointer (` *Base ` ). Resolving a promoted field on a value whose
54+ embedded pointer is nil reports an error; it does not allocate the intermediate struct.
55+ - An anonymous field that is not a struct (e.g. an embedded named slice) promotes nothing and is
56+ unreachable.
57+ - Maps must be keyed by a string type. A named string type is converted; ` map[int]V ` and friends
58+ cannot be addressed by a pointer and report an error.
59+ - ` Set ` with a nil value (what ` encoding/json ` decodes a JSON null into) writes the zero value when
60+ the target can hold nil — interface, pointer, map, slice, chan, func. On a target that cannot
61+ represent null (a ` string ` field, an element of ` []int ` ) it reports an error rather than
62+ substituting a zero value. Setting a map member to nil keeps the member; it does not delete it.
63+ - The RFC 6901 ` "-" ` array suffix ** is** supported on ` Pointer.Set ` as an append operation
64+ (RFC 6902 convention). On ` Pointer.Get ` and ` Pointer.Offset ` it is always an error per
65+ RFC 6901 §4. See ` ErrDashToken ` .
3266
3367## Dependencies
3468
35- - ` github.com/go-openapi/swag/jsonname ` — struct tag to JSON field name resolution
3669- ` github.com/go-openapi/testify/v2 ` — test-only assertions (zero-dep fork of ` stretchr/testify ` )
3770
71+ The module has no non-test dependency. ` jsonname ` is a subpackage of this repository, not the
72+ similarly named ` github.com/go-openapi/swag/jsonname ` .
73+
3874## Conventions
3975
4076- All ` .go ` files must have SPDX license headers (Apache-2.0).
4177- Commits require DCO sign-off (` git commit -s ` ).
42- - Linting: ` golangci-lint run ` — config in ` .golangci.yml ` (posture: ` default: all ` with explicit disables).
78+ - Linting: ` golangci-lint run ` — config in ` .golangci.yml ` (posture: ` default: all ` with explicit
79+ disables). Format with ` golangci-lint fmt ` , and check a change with
80+ ` golangci-lint run --new-from-rev master ` .
4381- Every ` //nolint ` directive ** must** have an inline comment explaining why.
44- - Tests: ` go test ./... ` with ` -race ` . CI runs on ` {ubuntu, macos, windows} x {stable, oldstable} ` .
82+ - Tests: ` go test ./... ` with ` -race ` . CI runs ` {ubuntu, macos, windows} x {stable, oldstable} ` ,
83+ via the shared ` go-openapi/ci-workflows/.github/workflows/go-test.yml ` .
4584- Test framework: ` github.com/go-openapi/testify/v2 ` (not ` stretchr/testify ` ).
4685
4786See ` .github/copilot/ ` (symlinked to ` .claude/rules/ ` ) for detailed rules on Go conventions, linting, testing, and contributions.
0 commit comments