ard

package module
v0.2.17 Latest Latest
Warning

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

Go to latest
Published: Mar 28, 2024 License: Apache-2.0 Imports: 21 Imported by: 37

README

Agnostic Raw Data (ARD) for Go

License Go Reference Go Report Card

A library to work with non-schematic data and consume it from various standard formats.

What is ARD? See here. Some people gloss it as "JSON", but that's misleading and ultimately unhelpful because JSON is merely a representation format for the data, and a rather limited format at that (e.g. it does not preserve the distinction between integers and floats).

This library supports several representation formats for ARD:

It is also implemented in Python.

And check out the ardconv ARD conversion tool.

Features

Read ARD from any Go Reader or decode from strings:

import (
	"fmt"
	"strings"
	"github.com/tliron/go-ard"
)

var yamlRepresentation = `
first:
  property1: Hello
  property2: 1.2
  property3:
  - 1
  - 2
  - second:
      property1: World
`

func main() {
	if value, _, err := ard.Read(strings.NewReader(yamlRepresentation), "yaml", false); err == nil {
		fmt.Printf("%v\n", value)
	}
}

Some formats (only YAML currently) support a Locator interface for finding the line and column for each data element, very useful for error messages:

var yamlRepresentation = `
first:
  property1: Hello
  property2: 1.2
  property3: [ 1, 2 ]
`

func main() {
	if _, locator, err := ard.Decode(yamlRepresentation, "yaml", true); err == nil {
		if locator != nil {
			if line, column, ok := locator.Locate(
				ard.NewMapPathElement("first"),
				ard.NewFieldPathElement("property3"),
				ard.NewListPathElement(0),
			); ok {
				fmt.Printf("%d, %d\n", line, column) // 5, 16
			}
		}
	}
}

Unmarshal ARD into Go structs:

var data = ard.Map{ // "ard.Map" is an alias for "map[any]any"
	"FirstName": "Gordon",
	"lastName":  "Freeman",
	"nicknames": ard.List{"Tigerbalm", "Stud Muffin"}, // "ard.List" is an alias for "[]any"
	"children": ard.List{
		ard.Map{
			"FirstName": "Bilbo",
		},
		ard.StringMap{ // "ard.StringMap" is an alias for "map[string]any"
			"FirstName": "Frodo",
		},
		nil,
	},
}

type Person struct {
	FirstName string    // property name will be used as field name
	LastName  string    `ard:"lastName"`   // "ard" tags work like familiar "json" and "yaml" tags
	Nicknames []string  `yaml:"nicknames"` // actually, go-ard will fall back to "yaml" tags by default
	Children  []*Person `json:"children"`  // ...and "json" tags, too
}

func main() {
	reflector := ard.NewReflector() // configurable; see documentation
	var p Person
	if err := reflector.Pack(data, &p); err == nil {
		fmt.Printf("%+v\n", p)
	}
}

Copy, merge, and compare:

func main() {
	data_ := ard.Copy(data).(ard.Map)
	fmt.Printf("%t\n", ard.Equals(data, data_))
	ard.Merge(data, ard.Map{"role": "hero", "children": ard.List{"Gollum"}}, true)
	fmt.Printf("%v\n", data)
}

Node-based path traversal:

var data = ard.Map{
	"first": ard.Map{
		"property1": "Hello",
		"property2": ard.StringMap{
			"second": ard.Map{
				"property3": 1}}}}

func main() {
	if p1, ok := ard.With(data).Get("first", "property1").String(); ok {
		fmt.Println(p1)
	}
	if p2, ok := ard.With(data).Get("first", "property2", "second", "property3").ConvertSimilar().Float(); ok {
		fmt.Printf("%f\n", p2)
	}
	if p3, ok := ard.With(data).GetPath("first.property2.second.property3", ".").ConvertSimilar().Float(); ok {
		fmt.Printf("%f\n", p3)
	}
}

By default go-ard reads maps into map[any]any, but you can normalize for either map[any]any or map[string]map (Go's built-in JSON encoder unfortunately requires the latter):

import "encoding/json"

var data = ard.Map{ // remember, these are "map[any]any"
	"person": ard.Map{
		"age": uint(120),
	},
}

func main() {
	if data_, ok := ard.CopyMapsToStringMaps(data); ok { // otherwise "encoding/json" won't be able to encode the "map[any]any"
		json.NewEncoder(os.Stdout).Encode(data_)
	}
}

Introducing the XJSON (eXtended JSON) format that adds support for missing ARD types: integers, unsigned integers, and maps with non-string keys:

var data = ard.Map{
	"person": ard.Map{
		"age": uint(120),
	},
}

func main() {
	if data_, err := ard.PrepareForEncodingXJSON(data, false, nil); err == nil { // will conveniently also normalize to "map[string]any" for "encoding/json" to work
		if j, err := json.Marshal(data_); err == nil {
			fmt.Println(string(j)) // {"map":{"age":{"$ard.uinteger":"120"}}}
			if data__, _, err := ard.Decode(j, "xjson", false); err == nil {
				fmt.Printf("%v\n", data__)
			}
		}
	}
}

Documentation

Index

Constants

View Source
const (
	XJSONIntegerCode  = "$ard.integer"
	XJSONUIntegerCode = "$ard.uinteger"
	XJSONBytesCode    = "$ard.bytes"
	XJSONMapCode      = "$ard.map"
)
View Source
const (
	XMLNilTag           = "nil"
	XMLBytesTag         = "bytes"
	XMLListTag          = "list"
	XMLMapTag           = "map"
	XMLMapEntryTag      = "entry"
	XMLMapEntryKeyTag   = "key"
	XMLMapEntryValueTag = "value"
)

Variables

View Source
var NoNode = &Node{nil, nil, "", false, false}

This singleton is returned from all node functions when no node is found.

Functions

func Decode

func Decode(code []byte, format string, locate bool) (Value, Locator, error)

Decodes supported formats to an ARD Value.

All resulting maps are guaranteed to be Map (and not StringMap).

If locate is true then a Locator will be returned if possible. Currently only YAML decoding supports this feature.

Supported formats are "yaml", "json", "xjson", "xml", "cbor", and "messagepack".

func DecodeTemplate added in v0.2.0

func DecodeTemplate(template string, data any, format string, locate bool) (Value, Locator, error)

Convenience function to parse and render a template and then decode it.

Would only be useful for text-based formats, so not CBOR and MessagePack.

See text/template.

func DecodeYAML

func DecodeYAML(code []byte, locate bool) (Value, Locator, error)

Decodes YAML to an ARD Value. If more than one YAML document is present (i.e. separated by `---`) then only the first will be decoded with the remainder ignored.

When locate is true will also return a Locator for the value, otherwise will return nil.

Note that the YAML implementation uses the yamlkeys library, so that arbitrarily complex map keys are supported and decoded into ARD Map. If you need to manipulate these maps you should use the yamlkeys utility functions.

func Equals

func Equals(a Value, b Value) bool

Checks for deep equality between two ARD values.

Primitives are compared via the `=` operator.

Note that Map and StringMap are treated as unequal. To gloss over the difference in type, call CopyStringMapsToMaps on one or both of the values first.

func FindYAMLNode

func FindYAMLNode(node *yaml.Node, path ...PathElement) *yaml.Node

func IsBoolean

func IsBoolean(value Value) bool

Returns true if value is a [bool].

(TypeValidator signature)

func IsBytes

func IsBytes(value Value) bool

Returns true if value is []byte.

(TypeValidator signature)

func IsList

func IsList(value Value) bool

Returns true if value is a List ([]any).

(TypeValidator signature)

func IsMap

func IsMap(value Value) bool

Returns true if value is a Map (map[any]any).

(TypeValidator signature)

func IsNull

func IsNull(value Value) bool

Returns true if value is nil.

(TypeValidator signature)

func IsPrimitiveType

func IsPrimitiveType(value Value) bool

Returns true if value is a string, bool, int64, int32, int16, int8, int, uint64, uint32, uint16, uint8, uint, float64, float32, nil, []byte, or time.Time.

func IsString

func IsString(value Value) bool

Returns true if value is a string.

(TypeValidator signature)

func IsTimestamp

func IsTimestamp(value Value) bool

Returns true if value is a time.Time.

(TypeValidator signature)

func MapKeyToString added in v0.2.0

func MapKeyToString(key any) string

Provides consistent stringification of keys for ARD StringMap.

Used by functions such as ConvertMapsToStringMaps and CopyMapsToStringMaps.

func MarshalMessagePack added in v0.2.1

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

Marshals MessagePack with support for "json" field tags.

func NewMessagePackDecoder added in v0.2.1

func NewMessagePackDecoder(reader io.Reader) *msgpack.Decoder

MessagePack decoder that supports "json" field tags.

func NewMessagePackEncoder added in v0.2.1

func NewMessagePackEncoder(writer io.Writer) *msgpack.Encoder

MessagePack encode that supports "json" field tags.

func PackXJSON added in v0.2.0

func PackXJSON(value Value) (any, bool)

func PackXML added in v0.2.0

func PackXML(value Value) any

func PrepareForEncodingXJSON added in v0.2.0

func PrepareForEncodingXJSON(value Value, inPlace bool, reflector *Reflector) (any, error)

Prepares an ARD Value for encoding via xml.Encoder.

If inPlace is false then the function is non-destructive: the returned data structure is a ValidCopy of the value argument. Otherwise, the value may be changed during preparation.

The reflector argument can be nil, in which case a default reflector will be used.

func PrepareForEncodingXML added in v0.2.0

func PrepareForEncodingXML(value Value, inPlace bool, reflector *Reflector) (any, error)

Prepares an ARD Value for encoding via xml.Encoder.

If inPlace is false then the function is non-destructive: the returned data structure is a ValidCopy of the value argument. Otherwise, the value may be changed during preparation.

The reflector argument can be nil, in which case a default reflector will be used.

func Read

func Read(reader io.Reader, format string, locate bool) (Value, Locator, error)

Reads and decodes supported formats to ARD.

All resulting maps are guaranteed to be Map (and not StringMap).

If locate is true then a Locator will be returned if possible. Currently only YAML decoding supports this feature.

Supported formats are "yaml", "json", "xjson", "xml", "cbor", and "messagepack".

func ReadURL added in v0.1.1

func ReadURL(context contextpkg.Context, url exturl.URL, format string, forceFormat bool, locate bool) (Value, Locator, error)

Convenience function to read from a URL. Calls Read.

When forceFormat is true the format argument will be used. When it's false the format will be attempted to be extracted from the URL using [URL.Format]. If it can't be determined then the format argument will be used as a fallback.

func ReadYAML

func ReadYAML(reader io.Reader, locate bool) (Value, Locator, error)

Reads YAML from an io.Reader and decodes it to an ARD Value. If more than one YAML document is present (i.e. separated by `---`) then only the first will be decoded with the remainder ignored.

When locate is true will also return a Locator for the value, otherwise will return nil.

Note that the YAML implementation uses the yamlkeys library, so that arbitrarily complex map keys are supported and decoded into ARD Map. If you need to manipulate these maps you should use the yamlkeys utility functions.

func ToYAMLDocumentNode

func ToYAMLDocumentNode(value Value, verbose bool, reflector *Reflector) (*yaml.Node, error)

func ToYAMLNode

func ToYAMLNode(value Value, verbose bool) (*yaml.Node, bool)

func UnmarshalMessagePack added in v0.2.1

func UnmarshalMessagePack(data []byte, value any) error

Unmarshals MessagePack with support for "json" field tags.

func UnpackXJSONBytes added in v0.2.0

func UnpackXJSONBytes(code StringMap) ([]byte, bool)

func UnpackXJSONInteger added in v0.2.0

func UnpackXJSONInteger(code StringMap) (int64, bool)

func UnpackXJSONUInteger added in v0.2.0

func UnpackXJSONUInteger(code StringMap) (uint64, bool)

func Validate added in v0.2.1

func Validate(code []byte, format string) error

Validates that data is of a supported format. Returns nil if valid, otherwise it will be the validation error.

While you can use Read to validate data, this function is optimized to be more lightweight. On other hand, this function does not do any schema validation (for example for XML), so if this function returns no error it does not guarantee that Read would also not return an error.

func ValidateCBOR added in v0.2.1

func ValidateCBOR(code []byte, base64 bool) error

If base64 is true then the data will first be fully read and decoded from Base64 to bytes.

func ValidateJSON added in v0.2.1

func ValidateJSON(code []byte) error

func ValidateMessagePack added in v0.2.1

func ValidateMessagePack(code []byte, base64 bool) error

If base64 is true then the data will first be fully read and decoded from Base64 to bytes.

func ValidateXML added in v0.2.1

func ValidateXML(code []byte) error

func ValidateYAML added in v0.2.1

func ValidateYAML(code []byte) error

func ValueToString

func ValueToString(value Value) string

Provides consistent stringification of primitive ARD Value.

Non-ARD types will be converted via util.ToString.

Types

type FromARD

type FromARD interface {
	FromARD(reflector *Reflector) (any, error)
}

Structs can implement their own custom packing with this interface.

type List

type List = []Value

An alias used to signify a list of ARD Value.

func ReadAllYAML

func ReadAllYAML(reader io.Reader) (List, error)

type Locator

type Locator interface {
	Locate(path ...PathElement) (int, int, bool)
}

type Map

type Map = map[Value]Value

An alias used to signify a map of ARD Value in which the key is also a Value. Note that this type does not protect its users against using invalid keys. Keys must be both hashable comparable.

func UnpackXJSONMap added in v0.2.0

func UnpackXJSONMap(code StringMap, useStringMaps bool) (Map, bool)

type Node

type Node struct {
	Value Value
	// contains filtered or unexported fields
}

func With added in v0.2.12

func With(data any) *Node

Creates an extractable, convertible, traversable, and modifiable wrapper (a Node) for an ARD Value.

func (*Node) Append

func (self *Node) Append(value Value) bool

Appends a value to a List and calls Node.Set.

Will fail and return false if there's no containing node or it's not Map or StringMap, or if this node is not a List.

func (*Node) Boolean

func (self *Node) Boolean() (bool, bool)

Returns (bool, true) if the node is a bool.

If Node.ConvertSimilar was called then will call Node.String and then strconv.ParseBool, with failures returning (false, false). Thus "true", "1", and numerical 1 (both ints and floats) will all be interpreted as boolean true.

By default will fail on nil values. Call Node.NilMeansZero to interpret nil as false.

func (*Node) Bytes

func (self *Node) Bytes() ([]byte, bool)

Returns ([]byte, true) if the node is a []byte.

If Node.ConvertSimilar was called and the node is a string then will attempt to decode it as base64, with failures returning (false, false).

By default will fail on nil values. Call Node.NilMeansZero to interpret nil as an empty []byte.

func (*Node) ConvertSimilar

func (self *Node) ConvertSimilar() *Node

Returns a copy of this node for which similarly-typed values are allowed and converted to the requested type. For example, Node.Float on an integer or unsigned integer would convert it to float.

func (*Node) Delete added in v0.2.7

func (self *Node) Delete() bool

Deletes this node's key from the containing node's map.

Will fail and return false if there's no containing node or it's not Map or StringMap.

func (*Node) Float

func (self *Node) Float() (float64, bool)

Returns (float64, true) if the node is a float64 or a float32.

If Node.ConvertSimilar was called then will convert all other number types (int64, int32, int16, int8, int, uint64, uint32, uint16, uint8, and uint) to a float64 and return true (unless we are NoNode).

Precision may be lost.

By default will fail on nil values. Call Node.NilMeansZero to interpret nil as 0.0.

func (*Node) ForceGet added in v0.2.11

func (self *Node) ForceGet(keys ...Value) *Node

Similar to Node.Get except that along the way new maps will be created if they do not exist and the key isn't already in use by something that is not a map. The type of the created map will match that of the containing map, either Map or StringMap. If the final key does not exist then a node with a nil value, contained in the previous node, will be returned. You can thus call Node.Set on it to set the value for the final key.

Thus the idiomatic safe way to set a nested value is like so:

if ok := ard.With(value).ForceGet("key1", "key2", "key3").Set("value"); ok { ... }

If you called Node.NilMeansZero, then take care when extracting data from the returned node, e.g. via Node.String, Node.Integer, etc. If the final key does not exist then these functions would still succeed.

For StringMap keys are converted using MapKeyToString.

func (*Node) ForceGetPath added in v0.2.11

func (self *Node) ForceGetPath(path string, separator string) *Node

Convenience method to call Node.ForceGet with PathToKeys.

func (*Node) Get

func (self *Node) Get(keys ...Value) *Node

Gets a nested node by recursively following keys. Thus all keys except the final one refer to nodes that must be Map or StringMap. Returns NoNode if any of the keys is not found along the way.

Thus the idiomatic safe way to get a nested value is like so:

if s, ok := ard.With(value).Get("key1", "key2", "key3").String(); ok { ... }

For StringMap keys are converted using MapKeyToString.

func (*Node) GetPath added in v0.2.11

func (self *Node) GetPath(path string, separator string) *Node

Convenience method to call Node.Get with PathToKeys.

func (*Node) Integer

func (self *Node) Integer() (int64, bool)

Returns (int64, true) if the node is an int64, int32, int16, int8, or int.

If Node.ConvertSimilar was called then will convert all other number types (uint64, uint32, uint16, uint8, uint, float64, and float32) to an int64 and return true (unless we are NoNode). Precision may be lost.

By default will fail on nil values. Call Node.NilMeansZero to interpret nil as 0.

func (*Node) List

func (self *Node) List() (List, bool)

Returns (List, true) if the node is a List.

If Node.ConvertSimilar was called then will convert other lists to a List.

By default will fail on nil values. Call Node.NilMeansZero to interpret nil as an empty List.

func (*Node) Map

func (self *Node) Map() (Map, bool)

Returns (Map, true) if the node is a Map.

If Node.ConvertSimilar was called then will convert other maps to a Map and return true.

By default will fail on nil values. Call Node.NilMeansZero to interpret nil as an empty Map.

func (*Node) NilMeansZero

func (self *Node) NilMeansZero() *Node

Returns a copy of this node for which nil values are allowed and interpreted as the zero value. For example, Node.String on nil would return an empty string.

func (*Node) Set added in v0.2.9

func (self *Node) Set(value Value) bool

Sets the value of this node and its key in the containing map.

Will fail and return false if there's no containing node or it's not Map or StringMap.

func (*Node) String

func (self *Node) String() (string, bool)

Returns (string, true) if the node is a string.

If Node.ConvertSimilar was called then will convert any value to a string representation using ValueToString and return true (unless we are NoNode).

By default will fail on nil values. Call Node.NilMeansZero to interpret nil as an empty string.

func (*Node) StringList

func (self *Node) StringList() ([]string, bool)

Returns ([]string, true) if the node is List and all its elements are strings. (Will avoid copying if the node is already a []string, which doesn't occur in valid ARD.)

If Node.ConvertSimilar was called then will convert all other lists to []string with all elements to their string representations and return true. Values are converted using ValueToString.

By default will fail on nil values. Call Node.NilMeansZero to interpret nil as an empty []string.

func (*Node) StringMap

func (self *Node) StringMap() (StringMap, bool)

Returns (StringMap, true) if the node is a StringMap.

If Node.ConvertSimilar was called then will convert other maps to a StringMap and return true. Keys are converted using MapKeyToString.

By default will fail on nil values. Call Node.NilMeansZero to interpret nil as an empty StringMap.

func (*Node) UnsignedInteger

func (self *Node) UnsignedInteger() (uint64, bool)

Returns (uint64, true) if the node is an uint64, uint32, uint16, uint8, or uint.

If Node.ConvertSimilar was called then will convert all other number types (int64, int32, int16, int8, int, float64, and float32) to an uint64 and return true (unless we are NoNode). Precision may be lost.

By default will fail on nil values. Call Node.NilMeansZero to interpret nil as 0.

type Path

type Path []PathElement

func (Path) Append

func (self Path) Append(element PathElement) Path

func (Path) AppendField

func (self Path) AppendField(name string) Path

func (Path) AppendList

func (self Path) AppendList(index int) Path

func (Path) AppendMap

func (self Path) AppendMap(name string) Path

func (Path) AppendSequencedList

func (self Path) AppendSequencedList(index int) Path

func (Path) String

func (self Path) String() string

(fmt.Stringer interface)

type PathElement

type PathElement struct {
	Type  PathElementType
	Value any // string for FieldPathType and MapPathType; int for ListPathType and SequencedListPathType
}

func NewFieldPathElement

func NewFieldPathElement(name string) PathElement

func NewListPathElement

func NewListPathElement(index int) PathElement

func NewMapPathElement

func NewMapPathElement(name string) PathElement

func NewSequencedListPathElement

func NewSequencedListPathElement(index int) PathElement

type PathElementType

type PathElementType int
const (
	FieldPathType         PathElementType = 0
	MapPathType           PathElementType = 1
	ListPathType          PathElementType = 2
	SequencedListPathType PathElementType = 3
)

type Reflector

type Reflector struct {
	// When true, non-existing struct fields will be ignored when packing.
	// Otherwise, will result in a packing error.
	IgnoreMissingStructFields bool

	// When true, nil values will be packed into the zero value for the target type.
	// Otherwise, only nullable types will be supported in the target: pointers, maps,
	// and slices, and other types will result in a packing error.
	NilMeansZero bool

	// Used for both packing and unpacking. Processed in order.
	StructFieldTags []string

	// While StructFieldTags can be used to specify specific unpacked names, when
	// untagged this function, if set, will be used for translating field names to
	// their unpacked names.
	StructFieldNameMapper StructFieldNameMapperFunc
	// contains filtered or unexported fields
}

func NewReflector

func NewReflector() *Reflector

Creates a reflector with default struct field tags: "ard", "yaml", "json".

func (*Reflector) Pack

func (self *Reflector) Pack(value Value, packedValuePtr any) error

Packs an ARD value into Go types, recursively.

For Go struct field names, keys are converted from Map using MapKeyToString.

Structs can provide their own custom packing by implementing the FromARD interface.

packedValuePtr must be a pointer.

func (*Reflector) Unpack

func (self *Reflector) Unpack(packedValue any) (Value, error)

Unpacks Go types to ARD, recursively. Map is used for Go structs and maps.

For Go struct field names, keys are converted to StringMap using MapKeyToString.

Structs can provide their own custom unpacking by implementing the ToARD interface.

packedValuePtr must be a pointer.

func (*Reflector) UnpackStringMaps added in v0.2.14

func (self *Reflector) UnpackStringMaps(packedValue any) (Value, error)

Unpacks Go types to ARD, recursively. StringMap is used for Go structs and maps.

Keys are converted using MapKeyToString.

Structs can provide their own custom unpacking by implementing the ToARD interface.

packedValue can be a value or a pointer.

type StringMap

type StringMap = map[string]Value

An alias used to signify a map of ARD Value in which the key is always string. This alias is introduced for compability with certain parsers and encoders.

type StructFieldNameMapperFunc

type StructFieldNameMapperFunc func(fieldName string) string

type ToARD

type ToARD interface {
	ToARD(reflector *Reflector) (any, error)
}

Structs can implement their own custom unpacking with this interface.

type TypeName

type TypeName string
const (
	NoType TypeName = ""

	// Failsafe schema: https://yaml.org/spec/1.2/spec.html#id2802346
	TypeMap    TypeName = "ard.map"
	TypeList   TypeName = "ard.list"
	TypeString TypeName = "ard.string"

	// JSON schema: https://yaml.org/spec/1.2/spec.html#id2803231
	TypeBoolean TypeName = "ard.boolean"
	TypeInteger TypeName = "ard.integer"
	TypeFloat   TypeName = "ard.float"

	// Other schemas: https://yaml.org/spec/1.2/spec.html#id2805770
	TypeNull      TypeName = "ard.null"
	TypeBytes     TypeName = "ard.bytes"
	TypeTimestamp TypeName = "ard.timestamp"
)

func GetTypeName

func GetTypeName(value Value) TypeName

Returns a canonical name for all supported ARD types, including primitives, Map, List, and time.Time. Note that StringMap is not supported by this function.

Unspported types will use fmt.Sprintf("%T").

type TypeValidator

type TypeValidator = func(Value) bool

type Value

type Value = any

An alias used to signify that ARD values are expected, namely primitives, List, Map, and StringMap nested to any depth.

func ConvertMapsToStringMaps added in v0.2.0

func ConvertMapsToStringMaps(value Value) (Value, bool)

Converts any Map to StringMap recursively, ensuring that no Map will be present. Conversion happens in place, unless the input is itself a Map, in which case a new StringMap will be returned.

Keys are converted using MapKeyToString.

Returns true if any conversion occurred.

func ConvertStringMapsToMaps added in v0.2.0

func ConvertStringMapsToMaps(value Value) (Value, bool)

Converts any StringMap to Map recursively, ensuring that no StringMap will be present. Conversion happens in place, unless the input is itself a StringMap, in which case a new Map will be returned.

Returns true if any conversion occurred.

func Copy added in v0.2.0

func Copy(value Value) Value

Deep copy.

The input can be a mix of ARD and non-ARD values (e.g. Go structs). Non-ARD values will be left as is, thus the returned may not be valid ARD. To ensure a valid ARD result use ValidCopy.

Recurses into Map, StringMap, and List, creating new instances of each. Thus a Map is copied into a new Map and a StringMap is copied into a new StringMap. To convert them to a unified map type use CopyStringMapsToMaps or CopyMapsToStringMaps.

func CopyMapsToStringMaps added in v0.2.0

func CopyMapsToStringMaps(value Value) Value

Like Copy but converts all Map to StringMap.

Keys are converted using MapKeyToString.

For in-place conversion use ConvertStringMapsToMaps.

func CopyStringMapsToMaps added in v0.2.0

func CopyStringMapsToMaps(value Value) Value

Like Copy but converts all StringMap to Map.

For in-place conversion use ConvertStringMapsToMaps.

func DecodeCBOR

func DecodeCBOR(code []byte, base64 bool) (Value, error)

Decodes CBOR to an ARD Value.

If base64 is true then the data will first be fully read and decoded from Base64 to bytes.

func DecodeJSON

func DecodeJSON(code []byte, useStringMaps bool) (Value, error)

Decodes JSON to an ARD Value.

If useStringMaps is true returns maps as StringMap, otherwise they will be Map.

func DecodeMessagePack

func DecodeMessagePack(code []byte, base64 bool, useStringMaps bool) (Value, error)

Reads MessagePack from an io.Reader and decodes it to an ARD Value.

If base64 is true then the data will first be fully read and decoded from Base64 to bytes.

If useStringMaps is true returns maps as StringMap, otherwise they will be Map.

func DecodeXJSON added in v0.2.0

func DecodeXJSON(code []byte, useStringMaps bool) (Value, error)

Decodes JSON to an ARD Value while interpreting the XJSON extensions.

If useStringMaps is true returns maps as StringMap, otherwise they will be Map.

func DecodeXML added in v0.2.0

func DecodeXML(code []byte) (Value, error)

Decodes XML to an ARD Value.

A specific schema is expected (currently undocumented).

func Merge added in v0.2.2

func Merge(target Value, source Value, appendLists bool) Value

Deep merge of source value into target value. Map and StringMap are merged key by key, recursively.

When appendList is true then target list elements are appended to the source list, otherwise the source list is overridden (copied over).

The source value remains safe, in that all merged data is copied (via Copy) into the target, thus any changes made to the target will not affect the source. On the other hand, the target value is changed in place. Note that for arguments that are not Map or StringMap you must use the return value from this function because it may return a new target value, e.g. a new List slice when appendList is true. Thus a safe way to use this function is like so:

target = Merge(target, source, true)

func PathToKeys added in v0.2.5

func PathToKeys(path string, separator string) []Value

Convenience function to convert a string path to keys usable for Node.Get and Node.ForceGet.

Does a strings.Split with the provided separator.

func ReadCBOR

func ReadCBOR(reader io.Reader, base64 bool) (Value, error)

Reads CBOR from an io.Reader and decodes it to an ARD Value.

If base64 is true then the data will first be fully read and decoded from Base64 to bytes.

func ReadJSON

func ReadJSON(reader io.Reader, useStringMaps bool) (Value, error)

Reads JSON from an io.Reader and decodes it to an ARD Value.

If useStringMaps is true returns maps as StringMap, otherwise they will be Map.

func ReadMessagePack

func ReadMessagePack(reader io.Reader, base64 bool, useStringMaps bool) (Value, error)

Reads MessagePack from an io.Reader and decodes it to an ARD Value.

If base64 is true then the data will first be fully read and decoded from Base64 to bytes.

If useStringMaps is true returns maps as StringMap, otherwise they will be Map.

func ReadXJSON added in v0.2.0

func ReadXJSON(reader io.Reader, useStringMaps bool) (Value, error)

Reads JSON from an io.Reader and decodes it to an ARD Value while interpreting the XJSON extensions.

If useStringMaps is true returns maps as StringMap, otherwise they will be Map.

func ReadXML added in v0.2.0

func ReadXML(reader io.Reader) (Value, error)

Reads XML from an io.Reader and decodes it to an ARD Value.

A specific schema is expected (currently undocumented).

func Roundtrip

func Roundtrip(value Value, format string, reflector *Reflector) (Value, error)

Encodes and then decodes the value via a supported format.

Supported formats are "yaml", "json", "xjson", "xml", "cbor", and "messagepack".

While this function can be used to "canonicalize" values to ARD, it is generally be more efficient to call ValidCopy instead.

func RoundtripCBOR

func RoundtripCBOR(value Value) (Value, error)

func RoundtripJSON

func RoundtripJSON(value Value) (Value, error)

func RoundtripMessagePack

func RoundtripMessagePack(value Value) (Value, error)

func RoundtripXJSON added in v0.2.0

func RoundtripXJSON(value Value, reflector *Reflector) (Value, error)

func RoundtripXML added in v0.2.0

func RoundtripXML(value Value, reflector *Reflector) (Value, error)

func RoundtripYAML

func RoundtripYAML(value Value) (Value, error)

func UnpackXJSON added in v0.2.0

func UnpackXJSON(value any, useStringMaps bool) (Value, bool)

func UnpackXML added in v0.2.0

func UnpackXML(element *etree.Element) (Value, error)

func ValidCopy added in v0.2.0

func ValidCopy(value Value, reflector *Reflector) (Value, error)

Deep copy and return a valid ARD value.

The input can be a mix of ARD and non-ARD values (e.g. Go structs). The returned value is guaranteed to be valid ARD. This works by reflecting any non-ARD via the provided *Reflector. The reflector argument can be nil, in which case a default reflector will be used. To leave non-ARD values as is use Copy.

This function can be used to "canonicalize" values to ARD, for which is should generally be more efficient than calling Roundtrip.

Recurses into Map, StringMap, and List, creating new instances of each. Thus a Map is copied into a new Map and a StringMap is copied into a new StringMap. To convert them to a unified map type use ValidCopyStringMapsToMaps or ValidCopyMapsToStringMaps.

func ValidCopyMapsToStringMaps added in v0.2.0

func ValidCopyMapsToStringMaps(value Value, reflector *Reflector) (Value, error)

Like ValidCopy but converts all Map to StringMap.

Keys are converted using MapKeyToString.

For in-place conversion use ConvertMapsToStringMaps.

func ValidCopyStringMapsToMaps added in v0.2.0

func ValidCopyStringMapsToMaps(value Value, reflector *Reflector) (Value, error)

Like ValidCopy but converts all StringMap to Map.

For in-place conversion use ConvertStringMapsToMaps.

type XJSONBytes added in v0.2.0

type XJSONBytes []byte

func (XJSONBytes) MarshalJSON added in v0.2.0

func (self XJSONBytes) MarshalJSON() ([]byte, error)

(json.Marshaler interface)

type XJSONInteger added in v0.2.0

type XJSONInteger int64

func (XJSONInteger) MarshalJSON added in v0.2.0

func (self XJSONInteger) MarshalJSON() ([]byte, error)

(json.Marshaler interface)

type XJSONMap added in v0.2.0

type XJSONMap Map

func (XJSONMap) MarshalJSON added in v0.2.0

func (self XJSONMap) MarshalJSON() ([]byte, error)

(json.Marshaler interface)

type XJSONMapEntry added in v0.2.0

type XJSONMapEntry struct {
	Key   Value `json:"key"`
	Value Value `json:"value"`
}

func UnpackXJSONMapEntry added in v0.2.0

func UnpackXJSONMapEntry(entry Value, useStringMaps bool) (*XJSONMapEntry, bool)

type XJSONUInteger added in v0.2.0

type XJSONUInteger uint64

func (XJSONUInteger) MarshalJSON added in v0.2.0

func (self XJSONUInteger) MarshalJSON() ([]byte, error)

(json.Marshaler interface)

type XMLBytes added in v0.2.0

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

func (XMLBytes) MarshalXML added in v0.2.0

func (self XMLBytes) MarshalXML(encoder *xml.Encoder, start xml.StartElement) error

(xml.Marshaler interface)

type XMLList added in v0.2.0

type XMLList struct {
	Entries []any
}

func (XMLList) MarshalXML added in v0.2.0

func (self XMLList) MarshalXML(encoder *xml.Encoder, start xml.StartElement) error

(xml.Marshaler interface)

type XMLMap added in v0.2.0

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

func (XMLMap) MarshalXML added in v0.2.0

func (self XMLMap) MarshalXML(encoder *xml.Encoder, start xml.StartElement) error

(xml.Marshaler interface)

type XMLMapEntry added in v0.2.0

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

func NewXMLMapEntry added in v0.2.0

func NewXMLMapEntry(element *etree.Element) (XMLMapEntry, error)

func (XMLMapEntry) MarshalXML added in v0.2.0

func (self XMLMapEntry) MarshalXML(encoder *xml.Encoder, start xml.StartElement) error

(xml.Marshaler interface)

type XMLNil added in v0.2.0

type XMLNil struct{}

func (XMLNil) MarshalXML added in v0.2.0

func (self XMLNil) MarshalXML(encoder *xml.Encoder, start xml.StartElement) error

(xml.Marshaler interface)

type YAMLLocator

type YAMLLocator struct {
	RootNode *yaml.Node
}

func NewYAMLLocator

func NewYAMLLocator(rootNode *yaml.Node) *YAMLLocator

func (*YAMLLocator) Locate

func (self *YAMLLocator) Locate(path ...PathElement) (int, int, bool)

(Locator interface)

Jump to

Keyboard shortcuts

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