README

pointerstructure GoDoc

pointerstructure is a Go library for identifying a specific value within any Go structure using a string syntax.

pointerstructure is based on JSON Pointer (RFC 6901), but reimplemented for Go.

The goal of pointerstructure is to provide a single, well-known format for addressing a specific value. This can be useful for user provided input on structures, diffs of structures, etc.

Features

  • Get the value for an address

  • Set the value for an address within an existing structure

  • Delete the value at an address

  • Sorting a list of addresses

Installation

Standard go get:

$ go get github.com/mitchellh/pointerstructure

Usage & Example

For usage and examples see the Godoc.

A quick code example is shown below:

complex := map[string]interface{}{
	"alice": 42,
	"bob": []interface{}{
		map[string]interface{}{
			"name": "Bob",
		},
	},
}

value, err := pointerstructure.Get(complex, "/bob/0/name")
if err != nil {
	panic(err)
}

fmt.Printf("%s", value)
// Output:
// Bob

Continuing the example above, you can also set values:

value, err = pointerstructure.Set(complex, "/bob/0/name", "Alice")
if err != nil {
	panic(err)
}

value, err = pointerstructure.Get(complex, "/bob/0/name")
if err != nil {
	panic(err)
}

fmt.Printf("%s", value)
// Output:
// Alice

The library also supports Get operations on structs including using the pointer struct tag to override struct field names:

	input := struct {
		Values map[string]interface{} `pointer:"embedded"`
	}{
		Values: map[string]interface{}{
			"alice": 42,
			"bob": []interface{}{
				map[string]interface{}{
					"name": "Bob",
				},
			},
		},
	}

	value, err := Get(input, "/embedded/bob/0/name")
	if err != nil {
		panic(err)
	}

	fmt.Printf("%s", value)
// Output:
// Bob
Expand ▾ Collapse ▴

Documentation

Overview

    Package pointerstructure provides functions for identifying a specific value within any Go structure using a string syntax.

    The syntax used is based on JSON Pointer (RFC 6901).

    Index

    Examples

    Constants

    This section is empty.

    Variables

    View Source
    var (
    	// ErrNotFound is returned if a key in a query can't be found
    	ErrNotFound = errors.New("couldn't find key")
    
    	// ErrParse is returned if the query cannot be parsed
    	ErrParse = errors.New("first char must be '/'")
    
    	// ErrOutOfRange is returned if a query is referencing a slice
    	// or array and the requested index is not in the range [0,len(item))
    	ErrOutOfRange = errors.New("out of range")
    
    	// ErrInvalidKind is returned if the item is not a map, slice,
    	// array, or struct
    	ErrInvalidKind = errors.New("invalid value kind")
    
    	// ErrConvert is returned if an item is not of a requested type
    	ErrConvert = errors.New("couldn't convert value")
    )

    Functions

    func Get

    func Get(value interface{}, pointer string) (interface{}, error)

      Get reads the value at the given pointer.

      This is a shorthand for calling Parse on the pointer and then calling Get on that result. An error will be returned if the value cannot be found or there is an error with the format of pointer.

      Example
      Output:
      
      Bob
      

      func Set

      func Set(doc interface{}, pointer string, value interface{}) (interface{}, error)

        Set sets the value at the given pointer.

        This is a shorthand for calling Parse on the pointer and then calling Set on that result. An error will be returned if the value cannot be found or there is an error with the format of pointer.

        Set returns the complete document, which might change if the pointer value points to the root ("").

        Example
        Output:
        
        Alice
        

        func Sort

        func Sort(p []*Pointer)

          Sort does an in-place sort of the pointers so that they are in order of least specific to most specific alphabetized. For example: "/foo", "/foo/0", "/qux"

          This ordering is ideal for applying the changes in a way that ensures that parents are set first.

          Types

          type Config

          type Config struct {
          	// The tag name that pointerstructure reads for field names. This
          	// defaults to "pointer"
          	TagName string
          	// ValueTransformationHook is called on each reference token within the
          	// provided JSON Pointer when Get is used.  The returned value from this
          	// hook is then used for matching for all following parts of the JSON
          	// Pointer.  If this returns a nil interface Get will return an error.
          	ValueTransformationHook ValueTransformationHookFn
          }

          type Pointer

          type Pointer struct {
          	// Parts are the pointer parts. No escape codes are processed here.
          	// The values are expected to be exact. If you have escape codes, use
          	// the Parse functions.
          	Parts []string
          
          	// Config is the configuration controlling how items are looked up
          	// in structures.
          	Config Config
          }

            Pointer represents a pointer to a specific value. You can construct a pointer manually or use Parse.

            func MustParse

            func MustParse(input string) *Pointer

              MustParse is like Parse but panics if the input cannot be parsed.

              func Parse

              func Parse(input string) (*Pointer, error)

                Parse parses a pointer from the input string. The input string is expected to follow the format specified by RFC 6901: '/'-separated parts. Each part can contain escape codes to contain '/' or '~'.

                func (*Pointer) Delete

                func (p *Pointer) Delete(s interface{}) (interface{}, error)

                  Delete deletes the value specified by the pointer p in structure s.

                  When deleting a slice index, all other elements will be shifted to the left. This is specified in RFC6902 (JSON Patch) and not RFC6901 since RFC6901 doesn't specify operations on pointers. If you don't want to shift elements, you should use Set to set the slice index to the zero value.

                  The structures s must have non-zero values set up to this pointer. For example, if deleting "/bob/0/name", then "/bob/0" must be set already.

                  The returned value is potentially a new value if this pointer represents the root document. Otherwise, the returned value will always be s.

                  func (*Pointer) Get

                  func (p *Pointer) Get(v interface{}) (interface{}, error)

                    Get reads the value out of the total value v.

                    For struct values a `pointer:"<name>"` tag on the struct's fields may be used to override that field's name for lookup purposes. Alternatively the tag name used can be overridden in the `Config`.

                    func (*Pointer) IsRoot

                    func (p *Pointer) IsRoot() bool

                      IsRoot returns true if this pointer represents the root document.

                      func (*Pointer) Parent

                      func (p *Pointer) Parent() *Pointer

                        Parent returns a pointer to the parent element of this pointer.

                        If Pointer represents the root (empty parts), a pointer representing the root is returned. Therefore, to check for the root, IsRoot() should be called.

                        func (*Pointer) Set

                        func (p *Pointer) Set(s, v interface{}) (interface{}, error)

                          Set writes a value v to the pointer p in structure s.

                          The structures s must have non-zero values set up to this pointer. For example, if setting "/bob/0/name", then "/bob/0" must be set already.

                          The returned value is potentially a new value if this pointer represents the root document. Otherwise, the returned value will always be s.

                          func (*Pointer) String

                          func (p *Pointer) String() string

                            String returns the string value that can be sent back to Parse to get the same Pointer result.

                            type PointerSlice

                            type PointerSlice []*Pointer

                              PointerSlice is a slice of pointers that adheres to sort.Interface

                              func (PointerSlice) Len

                              func (p PointerSlice) Len() int

                              func (PointerSlice) Less

                              func (p PointerSlice) Less(i, j int) bool

                              func (PointerSlice) Swap

                              func (p PointerSlice) Swap(i, j int)

                              type ValueTransformationHookFn

                              type ValueTransformationHookFn func(reflect.Value) reflect.Value

                                ValueTransformationHookFn transforms a Go data structure into another. This is useful for situations where you want the JSON Pointer to not be an exact match to the structure of the Go struct or map, for example when working with protocol buffers' well-known types.