func (d *document) Process(processor ValueProcessor) error {
	return process(d.root, []string{}, d.separator, processor)
}
Process implements Document.
package gjp
import (
	"encoding/json"
	"github.com/tideland/golib/errors"
	"github.com/tideland/golib/stringex"
)
type PathValue struct {
	Path  string
	Value Value
}
type PathValues []PathValue
type ValueProcessor func(path string, value Value) error
type Document interface {
	json.Marshaler
	Length(path string) int
	SetValueAt(path string, value interface{}) error
	ValueAt(path string) Value
	Clear()
	Query(pattern string) (PathValues, error)
	Process(processor ValueProcessor) error
}
type document struct {
	separator string
	root      interface{}
}
func Parse(data []byte, separator string) (Document, error) {
	var root interface{}
	err := json.Unmarshal(data, &root)
	if err != nil {
		return nil, errors.Annotate(err, ErrUnmarshalling, errorMessages)
	}
	return &document{
		separator: separator,
		root:      root,
	}, nil
}
func NewDocument(separator string) Document {
	return &document{
		separator: separator,
	}
}
func (d *document) Length(path string) int {
	n, err := valueAt(d.root, splitPath(path, d.separator))
	if err != nil {
		return -1
	}
	o, ok := isObject(n)
	if ok {
		return len(o)
	}
	a, ok := isArray(n)
	if ok {
		return len(a)
	}
	return 1
}
func (d *document) SetValueAt(path string, value interface{}) error {
	parts := splitPath(path, d.separator)
	root, err := setValueAt(d.root, value, parts)
	if err != nil {
		return err
	}
	d.root = root
	return nil
}
func (d *document) ValueAt(path string) Value {
	n, err := valueAt(d.root, splitPath(path, d.separator))
	return &value{n, err}
}
func (d *document) Clear() {
	d.root = nil
}
func (d *document) Query(pattern string) (PathValues, error) {
	pvs := PathValues{}
	err := d.Process(func(path string, value Value) error {
		if stringex.Matches(pattern, path, false) {
			pvs = append(pvs, PathValue{
				Path:  path,
				Value: value,
			})
		}
		return nil
	})
	return pvs, err
}