daq

package module
v0.10.0 Latest Latest
Warning

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

Go to latest
Published: Apr 19, 2024 License: MIT Imports: 8 Imported by: 5

README

daq – Data Queries

Access nested properties in Go data structures.

Go Reference Go Report Card

Go code for working with dynamic data structures can sometimes become somewhat verbose. E.g. like this:

var data any
json.Unmarshal([]byte(`{
	"glossary": {
		"title": "example glossary",
		"GlossDiv": {
			"title": "S",
			"GlossList": {
				"GlossEntry": {
					"ID": "SGML",
					"GlossTerm": "Standard Generalized Markup Language"
				}
			}
		}
	}
}`), &data)

title := "-no title-"
jObj, ok := data.(map[string]any)
if !ok {
	fmt.Println(title)
	return
}
if data = jObj["glossary"]; data == nil {
	fmt.Println(title)
	return
}
if jObj, ok = data.(map[string]any); !ok {
	fmt.Println(title)
	return
}
if data = jObj["title"]; data == nil {
	fmt.Println(title)
	return
}
title, _ = data.(string)

fmt.Println(title)
// Output:
// example glossary

Package daq helps for example to make it much more concise:

var data any
json.Unmarshal([]byte(`{
	"glossary": {
		"title": "example glossary",
		"GlossDiv": {
			"title": "S",
			"GlossList": {
				"GlossEntry": {
					"ID": "SGML",
					"GlossTerm": "Standard Generalized Markup Language"
				}
			}
		}
	}
}`), &data)

title := StringOr("-no title-")(Get(data, "glossary", "title"))

fmt.Println(title)
// Output:
// example glossary

In addition, daq can do even more, e.g. evaluate static data structures with the same API, iterate and … please consult the reference.

Documentation

Overview

Access nested properties in Go data structures with Data Queries

Concepts

  • A query Result is a tuple (result value:any, missed steps:int), if missed steps is 0, the query was successful and the result is OK.

  • Use “assert functions” or “fallback functions” to easily extract an expected type from a query result. Both are based on “convert functions”.

  • The convert function for target type T is func(v any) (r T, err error). If conversion of v fails, err != nil and r is T's zero value. Otherwise, r is the conversion result.

  • Use As to create an assertion function from a convert function.

  • Use Fallback to create a fallback function from a convert function.

  • By convention, convert functions for target type <T> are named To<T>(). Predefined assert functions are named As<T>(), predefined fallback functions <T>Or().

  • Use Get as the general way to perform queries. Read on to find more specific and efficient ways to query:

    Index, Field, Key to step with int, string and any. Further SliceAny, DictAny, MapAny to get query results that can be asserted from typical generic Go data.

  • To extend daq to your own types write convert functions and familiarize with Stepper, Slice, Dict and Map.

Convert Functions for Go's numeric types

  • Signed and unsigned integer types are promoted to each other as long as the actual runtime value is in target type's range.

  • Float values are promoted to integer types if the actual float has no fraction, and it is in target type's range.

  • Complex values with imag()==0 are promoted to integer by promoting the real() part according to the float rules.

Example
var data any
json.Unmarshal([]byte(`{
		"a": 3.1415,
		"bs": [1, 2, 3]
	}`), &data)

res, _ := Get(data, "a") // Ignore error in example for brevity
fmt.Println(res.Value, res.Missed())

res, err := Get(data, "b") // This will fail, no "b"
fmt.Println(res.Value, res.Missed(), err)

x, _ := AsFloat64(Get(data, "bs", 1)) // Type assertion (encoding/json uses float64 for numbers)
fmt.Println(x)

x, _ = AsFloat64(Get(data, "bs", -1)) // Access backwards from end
fmt.Println(x)

x = Float64Or(-1)(Get(data, "bs", 3)) // Fallback to -1 if Get fails
fmt.Println(x)
Output:

3.1415 0
map[a:3.1415 bs:[1 2 3]] 1 <nil>
2
3
-1
Example (Readme_daq)
var data any
json.Unmarshal([]byte(`{
		"glossary": {
			"title": "example glossary",
			"GlossDiv": {
				"title": "S",
				"GlossList": {
					"GlossEntry": {
						"ID": "SGML",
						"GlossTerm": "Standard Generalized Markup Language"
					}
				}
			}
		}
	}`), &data)

title := StringOr("-no title-")(Get(data, "glossary", "title"))

fmt.Println(title)
Output:

example glossary
Example (Readme_plainGo)
var data any
json.Unmarshal([]byte(`{
		"glossary": {
			"title": "example glossary",
			"GlossDiv": {
				"title": "S",
				"GlossList": {
					"GlossEntry": {
						"ID": "SGML",
						"GlossTerm": "Standard Generalized Markup Language"
					}
				}
			}
		}
	}`), &data)

title := "-no title-"
jObj, ok := data.(map[string]any)
if !ok {
	fmt.Println(title)
	return
}
if data = jObj["glossary"]; data == nil {
	fmt.Println(title)
	return
}
if jObj, ok = data.(map[string]any); !ok {
	fmt.Println(title)
	return
}
if data = jObj["title"]; data == nil {
	fmt.Println(title)
	return
}
title, _ = data.(string)

fmt.Println(title)
Output:

example glossary

Index

Examples

Constants

This section is empty.

Variables

View Source
var DefaultMerge = Merge{
	Time: Time{time.RFC3339, time.RFC3339Nano},
}

Functions

func As added in v0.4.1

func As[T any](conv func(any) (T, error)) func(Result, error) (T, error)

As returns the assert function for the specified type conversion conv to type T. Assert functions take query results as input. In any case, assert functions

  • return the missed steps of the query result unchanged.

  • never return error==nil if the query result was not OK. If necessary, a NotFound error is used.

If the query itself returend an error, As returns the null value of T and the error. Otherwise it performs the conversion – even if the result was not OK.

This means that error==nil is only returned if the conversion of a complete query is successfully converted.

Example
data := struct {
	Foo int
	Bar string
}{
	Foo: 4711,
	Bar: "baz",
}
fmt.Println(As(ToString)(Get(data, "Foo")))
fmt.Println(As(ToString)(Get(data, "Bar")))
fmt.Println(As(ToString)(Get(data, "void")))
Output:

cannot convert int to string
baz <nil>
 cannot convert struct { Foo int; Bar string } to string

func AsBool

func AsBool(res Result, err error) (bool, error)
Example
fmt.Println(AsBool(Get(true)))
fmt.Println(BoolOr(false)(Get(4711)))
Output:

true <nil>
false

func AsComplex128 added in v0.6.0

func AsComplex128(res Result, err error) (complex128, error)

func AsComplex64 added in v0.6.0

func AsComplex64(res Result, err error) (complex64, error)

func AsDuration

func AsDuration(res Result, err error) (time.Duration, error)

func AsFloat32

func AsFloat32(res Result, err error) (float32, error)

func AsFloat64

func AsFloat64(res Result, err error) (float64, error)

func AsInt

func AsInt(res Result, err error) (int, error)

func AsInt16

func AsInt16(res Result, err error) (int16, error)

func AsInt32

func AsInt32(res Result, err error) (int32, error)

func AsInt64

func AsInt64(res Result, err error) (int64, error)

func AsInt8

func AsInt8(res Result, err error) (int8, error)

func AsString

func AsString(res Result, err error) (string, error)
Example
fmt.Println(StringOr("-")(DictAny(testExample).Get("a")))
fmt.Println(Fallback(ToString, "-")(Get(testExample, "a", 0, "d")))
Output:

-
foo

func AsTime

func AsTime(res Result, err error) (time.Time, error)

func AsUint

func AsUint(res Result, err error) (uint, error)

func AsUint16

func AsUint16(res Result, err error) (uint16, error)

func AsUint32

func AsUint32(res Result, err error) (uint32, error)

func AsUint64

func AsUint64(res Result, err error) (uint64, error)

func AsUint8

func AsUint8(res Result, err error) (uint8, error)

func AsUintPtr

func AsUintPtr(res Result, err error) (uintptr, error)

func BoolOr

func BoolOr(fallback bool) func(Result, error) bool

func Complex128Or added in v0.6.0

func Complex128Or(fallback complex128) func(Result, error) complex128

func Complex64Or added in v0.6.0

func Complex64Or(fallback complex64) func(Result, error) complex64

func DeepEqual added in v0.5.0

func DeepEqual(lhs, rhs any) bool

func DeepEqualFunc added in v0.5.0

func DeepEqualFunc(lhs, rhs any, eq func(any, any) bool) bool

func DictAnyOr added in v0.7.0

func DictAnyOr(fallback DictAny) func(Result, error) DictAny

func DictOr added in v0.4.1

func DictOr(fallback Dict) func(Result, error) Dict

func DurationOr

func DurationOr(fallback time.Duration) func(Result, error) time.Duration

func Fallback added in v0.7.0

func Fallback[T any](conv func(any) (T, error), fallback T) func(Result, error) T

Fallback returns a fallback function for the given type conversion conv. A fallback function always returns a value of expected type T. It returns the asserted value of As in case of success, As returns error==nil. Otherwise it returns the fallback.

func Float32Or

func Float32Or(fallback float32) func(Result, error) float32

func Float64Or

func Float64Or(fallback float64) func(Result, error) float64

func Int16Or

func Int16Or(fallback int16) func(Result, error) int16

func Int32Or

func Int32Or(fallback int32) func(Result, error) int32

func Int64Or

func Int64Or(fallback int64) func(Result, error) int64

func Int8Or

func Int8Or(fallback int8) func(Result, error) int8

func IntOr

func IntOr(fallback int) func(Result, error) int

func MapAnyOr added in v0.7.0

func MapAnyOr(fallback MapAny) func(Result, error) MapAny

func MapOr

func MapOr(fallback Map) func(Result, error) Map

func Must added in v0.6.0

func Must[T any](v T, err error) T

Must panics with err if err is not zero. Otherwise v is returned. – Remember that you must not expect someone else to recover from a panic you have caused. Must is best used in liaison with deferred RecoverDaQ in small scopes you control yourself.

Example
// Use Must / RecoverDaQ in a single function's scope.
myScope := func(data any) (err error) {
	defer RecoverDaQ(&err)

	val := Must(Get(data, "glossary", "GlossDiv", "GlossList"))
	fmt.Println("Get 1:", val, err)

	ls := Must(AsSliceAny(Get(data, "glossary", "GlossDiv", "GlossList")))
	fmt.Println("Get 2:", ls, err)

	return nil
}

// Parse some JSON data
var data any
err := json.Unmarshal([]byte(`{
		"glossary": {
			"title": "example glossary",
			"GlossDiv": {
				"title": "S",
				"GlossList": {
					"GlossEntry": {
						"ID": "SGML",
						"GlossTerm": "Standard Generalized Markup Language"
					}
				}
			}
		}
	}`), &data)
if err != nil {
	fmt.Println(err)
	return
}

// Now, run myScope
err = myScope(data)
if err != nil {
	fmt.Printf("myScope returned: %s\n", err)
}
Output:

Get 1: {map[GlossEntry:map[GlossTerm:Standard Generalized Markup Language ID:SGML]] 0} <nil>
myScope returned: cannot convert map[string]interface {} to daq.SliceAny

func RecoverDaQ added in v0.7.0

func RecoverDaQ(err *error)

RecoverDaQ only recovers from panics created with Must and sets err.

func SliceAnyOr added in v0.7.0

func SliceAnyOr(fallback SliceAny) func(Result, error) SliceAny

func SliceOr

func SliceOr(fallback Slice) func(Result, error) Slice

func StepEach added in v0.3.0

func StepEach(data any, do func(kind reflect.Kind, key, value any) error) error
Example (Array)
data := [4]any{0, '1', "two", nil}
err := StepEach(data, testPrintStep)
fmt.Println(err)
Output:

kind 'array': key=0 / value=0
kind 'array': key=1 / value=49
kind 'array': key=2 / value="two"
kind 'array': key=3 / value=<nil>
<nil>
Example (Atom)
err := StepEach(5180, testPrintStep)
fmt.Println(err)
Output:

kind 'invalid': key=<nil> / value=5180
<nil>
Example (Map)
data := map[any]any{
	false: "foo",
	7:     nil,
	"bar": 4711,
}
err := StepEach(data, testPrintStep)
fmt.Println(err)
Output:

kind 'map': key=false / value="foo"
kind 'map': key=7 / value=<nil>
kind 'map': key="bar" / value=4711
<nil>
Example (Slice)
data := []any{0, '1', "two", nil}
err := StepEach(data, testPrintStep)
fmt.Println(err)
Output:

kind 'slice': key=0 / value=0
kind 'slice': key=1 / value=49
kind 'slice': key=2 / value="two"
kind 'slice': key=3 / value=<nil>
<nil>
Example (Struct)
type Tstnest struct {
	Foo int
}
data := struct {
	Tstnest
	Bar  string
	Nest Tstnest
}{
	Tstnest: Tstnest{Foo: 4711},
	Bar:     "baz",
	Nest:    Tstnest{Foo: -1},
}
err := StepEach(data, testPrintStep)
fmt.Println(err)
Output:

kind 'struct': key="Foo" / value=4711
kind 'struct': key="Bar" / value="baz"
kind 'struct': key="Nest" / value=daq.Tstnest{Foo:-1}
<nil>

func StringOr

func StringOr(fallback string) func(Result, error) string

func TestingDeepEqual added in v0.5.0

func TestingDeepEqual(t testing.TB, lhs, rhs any) (diffCount int)

func TestingDeepEqualFunc added in v0.5.0

func TestingDeepEqualFunc(t testing.TB, lhs, rhs any, eq func(any, any) bool) (diffCount int)

func TimeOr

func TimeOr(fallback time.Time) func(Result, error) time.Time

func ToBool added in v0.4.1

func ToBool(v any) (bool, error)

func ToComplex128 added in v0.6.0

func ToComplex128(v any) (complex128, error)

func ToComplex64 added in v0.6.0

func ToComplex64(v any) (complex64, error)

func ToDuration added in v0.4.1

func ToDuration(v any) (time.Duration, error)

func ToFloat32 added in v0.4.1

func ToFloat32(v any) (float32, error)

func ToFloat64 added in v0.4.1

func ToFloat64(v any) (float64, error)

func ToInt added in v0.4.1

func ToInt(v any) (int, error)

func ToInt16 added in v0.4.1

func ToInt16(v any) (int16, error)

func ToInt32 added in v0.4.1

func ToInt32(v any) (int32, error)

func ToInt64 added in v0.4.1

func ToInt64(v any) (int64, error)

func ToInt8 added in v0.4.1

func ToInt8(v any) (int8, error)

func ToString added in v0.4.1

func ToString(v any) (string, error)

func ToTime added in v0.4.1

func ToTime(v any) (time.Time, error)
Example
t := time.Date(2023, 12, 29, 2, 4, 0, 0, time.UTC)
fmt.Println(ToTime(t))
fmt.Println(ToTime(&t))
fmt.Println(ToTime((*time.Time)(nil)))
Output:

2023-12-29 02:04:00 +0000 UTC <nil>
2023-12-29 02:04:00 +0000 UTC <nil>
0001-01-01 00:00:00 +0000 UTC <nil>

func ToUint added in v0.4.1

func ToUint(v any) (uint, error)

func ToUint16 added in v0.4.1

func ToUint16(v any) (uint16, error)

func ToUint32 added in v0.4.1

func ToUint32(v any) (uint32, error)

func ToUint64 added in v0.4.1

func ToUint64(v any) (uint64, error)

func ToUint8 added in v0.4.1

func ToUint8(v any) (uint8, error)

func ToUintPtr added in v0.4.1

func ToUintPtr(v any) (uintptr, error)

func Uint16Or

func Uint16Or(fallback uint16) func(Result, error) uint16

func Uint32Or

func Uint32Or(fallback uint32) func(Result, error) uint32

func Uint64Or

func Uint64Or(fallback uint64) func(Result, error) uint64

func Uint8Or

func Uint8Or(fallback uint8) func(Result, error) uint8

func UintOr

func UintOr(fallback uint) func(Result, error) uint

func UintPtrOr

func UintPtrOr(fallback uintptr) func(Result, error) uintptr

Types

type Alt

type Alt struct {
	S  any
	Or any
}
Example
data := []string{"foo", "bar", "baz"}
fmt.Println(Step(data, "bar"))
fmt.Println(Step(data, Alt{S: "bar", Or: 4711}))
Output:

{<nil> 1} key lookup: cannot use []string as daq.Map
{4711 0} <nil>

func (Alt) Step

func (a Alt) Step(data any) (Result, error)

type CollectionTypeError added in v0.5.0

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

func (CollectionTypeError) Error added in v0.5.0

func (e CollectionTypeError) Error() string

func (CollectionTypeError) Is added in v0.5.0

func (e CollectionTypeError) Is(err error) bool

type ConvertError added in v0.7.0

type ConvertError[T any] struct {
	Value any
}

func (ConvertError[T]) Error added in v0.7.0

func (e ConvertError[T]) Error() string

type Delta added in v0.5.0

type Delta struct {
	AtomEqual   func(lhs, rhs any) bool
	OnNotEqual  func(path []any, left, right any) error
	OnLeftOnly  func(path []any, val any) error
	OnRightOnly func(path []any, val any) error
}

func (*Delta) Compare added in v0.5.0

func (cmpr *Delta) Compare(l, r any) error

type Dict added in v0.4.1

type Dict interface {
	DaQGet(name string) (res Result, err error)
	DaQEachKey(do func(key string) error) error
}

Dict is queried with a string as name.

func AsDict added in v0.4.1

func AsDict(res Result, err error) (Dict, error)

func ToDict added in v0.4.1

func ToDict(v any) (Dict, error)

type DictAny added in v0.4.1

type DictAny map[string]any

func AsDictAny added in v0.7.0

func AsDictAny(res Result, err error) (DictAny, error)

func ToDictAny added in v0.7.0

func ToDictAny(v any) (DictAny, error)

func (DictAny) AsBool added in v0.7.0

func (d DictAny) AsBool(name string) (bool, error)

func (DictAny) AsComplex128 added in v0.7.0

func (d DictAny) AsComplex128(name string) (complex128, error)

func (DictAny) AsComplex64 added in v0.7.0

func (d DictAny) AsComplex64(name string) (complex64, error)

func (DictAny) AsDict added in v0.7.0

func (d DictAny) AsDict(name string) (Dict, error)

func (DictAny) AsDictAny added in v0.7.0

func (d DictAny) AsDictAny(name string) (DictAny, error)

func (DictAny) AsDuration added in v0.7.0

func (d DictAny) AsDuration(name string) (time.Duration, error)

func (DictAny) AsFloat32 added in v0.7.0

func (d DictAny) AsFloat32(name string) (float32, error)

func (DictAny) AsFloat64 added in v0.7.0

func (d DictAny) AsFloat64(name string) (float64, error)

func (DictAny) AsInt added in v0.7.0

func (d DictAny) AsInt(name string) (int, error)

func (DictAny) AsInt16 added in v0.7.0

func (d DictAny) AsInt16(name string) (int16, error)

func (DictAny) AsInt32 added in v0.7.0

func (d DictAny) AsInt32(name string) (int32, error)

func (DictAny) AsInt64 added in v0.7.0

func (d DictAny) AsInt64(name string) (int64, error)

func (DictAny) AsInt8 added in v0.7.0

func (d DictAny) AsInt8(name string) (int8, error)

func (DictAny) AsMap added in v0.7.0

func (d DictAny) AsMap(name string) (Map, error)

func (DictAny) AsMapAny added in v0.7.0

func (d DictAny) AsMapAny(name string) (MapAny, error)

func (DictAny) AsSlice added in v0.7.0

func (d DictAny) AsSlice(name string) (Slice, error)

func (DictAny) AsSliceAny added in v0.7.0

func (d DictAny) AsSliceAny(name string) (SliceAny, error)

func (DictAny) AsString added in v0.7.0

func (d DictAny) AsString(name string) (string, error)

func (DictAny) AsTime added in v0.7.0

func (d DictAny) AsTime(name string) (time.Time, error)

func (DictAny) AsUint added in v0.7.0

func (d DictAny) AsUint(name string) (uint, error)

func (DictAny) AsUint16 added in v0.7.0

func (d DictAny) AsUint16(name string) (uint16, error)

func (DictAny) AsUint32 added in v0.7.0

func (d DictAny) AsUint32(name string) (uint32, error)

func (DictAny) AsUint64 added in v0.7.0

func (d DictAny) AsUint64(name string) (uint64, error)

func (DictAny) AsUint8 added in v0.7.0

func (d DictAny) AsUint8(name string) (uint8, error)

func (DictAny) AsUintPtr added in v0.7.0

func (d DictAny) AsUintPtr(name string) (uintptr, error)

func (DictAny) BoolOr added in v0.7.0

func (d DictAny) BoolOr(name string, fallback bool) bool

func (DictAny) Complex128Or added in v0.7.0

func (d DictAny) Complex128Or(name string, fallback complex128) complex128

func (DictAny) Complex64Or added in v0.7.0

func (d DictAny) Complex64Or(name string, fallback complex64) complex64

func (DictAny) DaQEachKey added in v0.4.1

func (d DictAny) DaQEachKey(do func(key string) error) error

func (DictAny) DaQGet added in v0.4.1

func (d DictAny) DaQGet(n string) (Result, error)

func (DictAny) DurationOr added in v0.7.0

func (d DictAny) DurationOr(name string, fallback time.Duration) time.Duration

func (DictAny) Float32Or added in v0.7.0

func (d DictAny) Float32Or(name string, fallback float32) float32

func (DictAny) Float64Or added in v0.7.0

func (d DictAny) Float64Or(name string, fallback float64) float64

func (DictAny) Get added in v0.6.0

func (d DictAny) Get(name string) (Result, error)

func (DictAny) Int16Or added in v0.7.0

func (d DictAny) Int16Or(name string, fallback int16) int16

func (DictAny) Int32Or added in v0.7.0

func (d DictAny) Int32Or(name string, fallback int32) int32

func (DictAny) Int64Or added in v0.7.0

func (d DictAny) Int64Or(name string, fallback int64) int64

func (DictAny) Int8Or added in v0.7.0

func (d DictAny) Int8Or(name string, fallback int8) int8

func (DictAny) IntOr added in v0.7.0

func (d DictAny) IntOr(name string, fallback int) int

func (DictAny) StringOr added in v0.7.0

func (d DictAny) StringOr(name string, fallback string) string

func (DictAny) TimeOr added in v0.7.0

func (d DictAny) TimeOr(name string, fallback time.Time) time.Time

func (DictAny) Uint16Or added in v0.7.0

func (d DictAny) Uint16Or(name string, fallback uint16) uint16

func (DictAny) Uint32Or added in v0.7.0

func (d DictAny) Uint32Or(name string, fallback uint32) uint32

func (DictAny) Uint64Or added in v0.7.0

func (d DictAny) Uint64Or(name string, fallback uint64) uint64

func (DictAny) Uint8Or added in v0.7.0

func (d DictAny) Uint8Or(name string, fallback uint8) uint8

func (DictAny) UintOr added in v0.7.0

func (d DictAny) UintOr(name string, fallback uint) uint

func (DictAny) UintPtrOr added in v0.7.0

func (d DictAny) UintPtrOr(name string, fallback uintptr) uintptr

type FirstIdxOf added in v0.5.0

type FirstIdxOf []int
Example
data := []string{"foo", "bar", "baz"}
fmt.Println(Step(data, FirstIdxOf{99, 1})) // more efficient
fmt.Println(Step(data, FirstOf{99, 1}))    // more general
Output:

{bar 0} <nil>
{bar 0} <nil>

func (FirstIdxOf) Step added in v0.5.0

func (idxs FirstIdxOf) Step(data any) (res Result, err error)

type FirstKeyOf added in v0.5.0

type FirstKeyOf []any
Example
data := map[any]any{
	"foo": 1,
	"bar": 2,
	"baz": 3,
}
fmt.Println(Step(data, FirstKeyOf{"quux", "bar"})) // more efficient
fmt.Println(Step(data, FirstOf{"quux", "bar"}))    // more general
Output:

{2 0} <nil>
{2 0} <nil>

func (FirstKeyOf) Step added in v0.5.0

func (ns FirstKeyOf) Step(data any) (res Result, err error)

type FirstNameOf

type FirstNameOf []string
Example
data := map[string]int{
	"foo": 1,
	"bar": 2,
	"baz": 3,
}
fmt.Println(Step(data, FirstNameOf{"quux", "bar"})) // more efficient
fmt.Println(Step(data, FirstOf{"quux", "bar"}))     // more general
Output:

{2 0} <nil>
{2 0} <nil>

func (FirstNameOf) Step

func (ns FirstNameOf) Step(data any) (res Result, err error)

type FirstOf

type FirstOf []any

func (FirstOf) Step

func (keys FirstOf) Step(data any) (res Result, err error)

type Map

type Map interface {
	DaQGet(key any) (res Result, err error)
	DaQEachKey(do func(key any) error) error
}

Map is queried with any comparable value as key.

func AsMap

func AsMap(res Result, err error) (Map, error)

func ToMap added in v0.4.1

func ToMap(v any) (Map, error)

type MapAny added in v0.4.1

type MapAny map[any]any

func AsMapAny added in v0.7.0

func AsMapAny(res Result, err error) (MapAny, error)

func ToMapAny added in v0.7.0

func ToMapAny(v any) (MapAny, error)

func (MapAny) AsBool added in v0.7.0

func (m MapAny) AsBool(key any) (bool, error)

func (MapAny) AsComplex128 added in v0.7.0

func (m MapAny) AsComplex128(key any) (complex128, error)

func (MapAny) AsComplex64 added in v0.7.0

func (m MapAny) AsComplex64(key any) (complex64, error)

func (MapAny) AsDict added in v0.7.0

func (m MapAny) AsDict(key any) (Dict, error)

func (MapAny) AsDictAny added in v0.7.0

func (m MapAny) AsDictAny(key any) (DictAny, error)

func (MapAny) AsDuration added in v0.7.0

func (m MapAny) AsDuration(key any) (time.Duration, error)

func (MapAny) AsFloat32 added in v0.7.0

func (m MapAny) AsFloat32(key any) (float32, error)

func (MapAny) AsFloat64 added in v0.7.0

func (m MapAny) AsFloat64(key any) (float64, error)

func (MapAny) AsInt added in v0.7.0

func (m MapAny) AsInt(key any) (int, error)

func (MapAny) AsInt16 added in v0.7.0

func (m MapAny) AsInt16(key any) (int16, error)

func (MapAny) AsInt32 added in v0.7.0

func (m MapAny) AsInt32(key any) (int32, error)

func (MapAny) AsInt64 added in v0.7.0

func (m MapAny) AsInt64(key any) (int64, error)

func (MapAny) AsInt8 added in v0.7.0

func (m MapAny) AsInt8(key any) (int8, error)

func (MapAny) AsMap added in v0.7.0

func (m MapAny) AsMap(key any) (Map, error)

func (MapAny) AsMapAny added in v0.7.0

func (m MapAny) AsMapAny(key any) (MapAny, error)

func (MapAny) AsSlice added in v0.7.0

func (m MapAny) AsSlice(key any) (Slice, error)

func (MapAny) AsSliceAny added in v0.7.0

func (m MapAny) AsSliceAny(key any) (SliceAny, error)

func (MapAny) AsString added in v0.7.0

func (m MapAny) AsString(key any) (string, error)

func (MapAny) AsTime added in v0.7.0

func (m MapAny) AsTime(key any) (time.Time, error)

func (MapAny) AsUint added in v0.7.0

func (m MapAny) AsUint(key any) (uint, error)

func (MapAny) AsUint16 added in v0.7.0

func (m MapAny) AsUint16(key any) (uint16, error)

func (MapAny) AsUint32 added in v0.7.0

func (m MapAny) AsUint32(key any) (uint32, error)

func (MapAny) AsUint64 added in v0.7.0

func (m MapAny) AsUint64(key any) (uint64, error)

func (MapAny) AsUint8 added in v0.7.0

func (m MapAny) AsUint8(key any) (uint8, error)

func (MapAny) AsUintPtr added in v0.7.0

func (m MapAny) AsUintPtr(key any) (uintptr, error)

func (MapAny) BoolOr added in v0.7.0

func (m MapAny) BoolOr(key any, fallback bool) bool

func (MapAny) Complex128Or added in v0.7.0

func (m MapAny) Complex128Or(key any, fallback complex128) complex128

func (MapAny) Complex64Or added in v0.7.0

func (m MapAny) Complex64Or(key any, fallback complex64) complex64

func (MapAny) DaQEachKey added in v0.4.1

func (m MapAny) DaQEachKey(do func(key any) error) error

func (MapAny) DaQGet added in v0.4.1

func (m MapAny) DaQGet(key any) (Result, error)

func (MapAny) DurationOr added in v0.7.0

func (m MapAny) DurationOr(key any, fallback time.Duration) time.Duration

func (MapAny) Float32Or added in v0.7.0

func (m MapAny) Float32Or(key any, fallback float32) float32

func (MapAny) Float64Or added in v0.7.0

func (m MapAny) Float64Or(key any, fallback float64) float64

func (MapAny) Get added in v0.7.0

func (m MapAny) Get(key any) (Result, error)

func (MapAny) Int16Or added in v0.7.0

func (m MapAny) Int16Or(key any, fallback int16) int16

func (MapAny) Int32Or added in v0.7.0

func (m MapAny) Int32Or(key any, fallback int32) int32

func (MapAny) Int64Or added in v0.7.0

func (m MapAny) Int64Or(key any, fallback int64) int64

func (MapAny) Int8Or added in v0.7.0

func (m MapAny) Int8Or(key any, fallback int8) int8

func (MapAny) IntOr added in v0.7.0

func (m MapAny) IntOr(key, fallback int) int

func (MapAny) StringOr added in v0.7.0

func (m MapAny) StringOr(key any, fallback string) string

func (MapAny) TimeOr added in v0.7.0

func (m MapAny) TimeOr(key any, fallback time.Time) time.Time

func (MapAny) Uint16Or added in v0.7.0

func (m MapAny) Uint16Or(key any, fallback uint16) uint16

func (MapAny) Uint32Or added in v0.7.0

func (m MapAny) Uint32Or(key any, fallback uint32) uint32

func (MapAny) Uint64Or added in v0.7.0

func (m MapAny) Uint64Or(key any, fallback uint64) uint64

func (MapAny) Uint8Or added in v0.7.0

func (m MapAny) Uint8Or(key any, fallback uint8) uint8

func (MapAny) UintOr added in v0.7.0

func (m MapAny) UintOr(key any, fallback uint) uint

func (MapAny) UintPtrOr added in v0.7.0

func (m MapAny) UintPtrOr(key any, fallback uintptr) uintptr

type Merge added in v0.8.0

type Merge struct {
	Time Time
}
Example
var config = struct {
	Logging struct {
		Enabled bool
		Level   string
	}
	SrvAddr string
	Misc    any
}{
	SrvAddr: "localhost:8080",
}

// Loading initial data does not need merging
json.Unmarshal([]byte(`{
		"Logging": "info",
		"Misc": {
			"Foo": "bar"
		}
	}`), &config)
fmt.Printf("%+v\n", config)

// Loading more data does not merge Misc
json.Unmarshal([]byte(`{
		"Misc": {
			"Baz": "quux"
		},
		"SrvAddr": ":8081"
	}`), &config)
fmt.Printf("%+v\n", config)

// Using Merge does not simply overwrite Misc
tmp := make(map[string]any)
json.Unmarshal([]byte(`{
		"Logging": {
			"Enabled": true,
			"Level": "debug"
		},
		"Misc": {
			"Foo": "bar"
		}
	}`), &tmp)
DefaultMerge.Merge(&config, tmp)
fmt.Printf("%+v\n", config)
Output:

{Logging:{Enabled:false Level:} SrvAddr:localhost:8080 Misc:map[Foo:bar]}
{Logging:{Enabled:false Level:} SrvAddr::8081 Misc:map[Baz:quux]}
{Logging:{Enabled:true Level:debug} SrvAddr::8081 Misc:map[Baz:quux Foo:bar]}

func (*Merge) Merge added in v0.8.0

func (mrg *Merge) Merge(into, from any) (err error)

type Merger added in v0.8.0

type Merger interface {
	MergeDaQ(by *Merge, add any) error
}

type NotFound added in v0.6.0

type NotFound int

func (NotFound) Error added in v0.6.0

func (e NotFound) Error() string

func (NotFound) Is added in v0.6.0

func (e NotFound) Is(err error) bool

type Result added in v0.7.0

type Result struct {
	Value any
	// contains filtered or unexported fields
}

Result represents the outcome of a single- or multi-step query. It is not considered an error if a query does not find a result. Errors can be caused by invalid queries and are subject to idiomatic Go error handling.

Use Result.OK and Result.Missed to find out if a query did find a result.

func Field

func Field(data any, name string) (res Result, err error)

func Get

func Get(data any, path ...any) (res Result, err error)

Get queries data for an element by using the path of steps. See Step and Stepper from details on steps. Get terminates the query if a step is not successful. Get returns the last obtained value with the number of missing steps and, if applicable, the error of the last step.

Example
data := map[string]any{
	"a": []any{
		map[string]any{
			"b": map[any]any{"c": 3},
			"d": "foo",
		},
		false,
	},
}
var i int = IntOr(-1)(Get(data, "a", 0, "b", "c"))
fmt.Println(i)
fmt.Println(Get(data, "a", 0, "b", "d"))
fmt.Println(Get(nil, "a", 0, "b", "d"))
Output:

3
{map[c:3] 1} <nil>
{<nil> 4} <nil>

func Index

func Index(data any, index int) (res Result, err error)

func Key added in v0.4.1

func Key(data, key any) (res Result, err error)

func NewResult added in v0.7.0

func NewResult(value any, missedSteps int) Result

func Step

func Step(data, step any) (res Result, err error)

Step does a single query step from data. If step implements Stepper, step.Step() is used. Otherwise Go types int and string are acceped as steps in a query.

- With int you can go one step from Slice or Map to an element.

- With string you can go one step from Dict or Map to an element.

func (Result) Missed added in v0.7.0

func (r Result) Missed() int

Missed returns the number of missed steps of the query that created r. A query is successful if all steps of the query were successful i.e. there are no missed steps.

func (Result) OK added in v0.7.0

func (r Result) OK() bool

OK returns true only for results of successful queries, i.e. if Missed returns 0.

func (Result) SplitPath added in v0.7.0

func (r Result) SplitPath(p []any) (done, missing []any)

SplitPath may panic if p is shorter than the path that created s.

type Slice

type Slice interface {
	DaQGet(index int) (res Result, err error)
	DaQLen() int
}

Slice is queried with an int index. Negative indices access from the end with -1 being the last element and -DaQLen() the first.

func AsSlice

func AsSlice(res Result, err error) (Slice, error)
Example
s := SliceOr(nil)(DictAny(testExample).Get("a"))
for i := 0; i < s.DaQLen(); i++ {
	res, err := s.DaQGet(i)
	must.Do(err)
	fmt.Println(res.Value, res.Missed())
}
Output:

map[b:map[c:3] d:foo] 0
false 0

func ToSlice added in v0.4.1

func ToSlice(v any) (Slice, error)

type SliceAny added in v0.4.1

type SliceAny []any

func AsSliceAny added in v0.7.0

func AsSliceAny(res Result, err error) (SliceAny, error)

func ToSliceAny added in v0.7.0

func ToSliceAny(v any) (SliceAny, error)

func (SliceAny) AsBool added in v0.7.0

func (s SliceAny) AsBool(i int) (bool, error)

func (SliceAny) AsComplex128 added in v0.7.0

func (s SliceAny) AsComplex128(i int) (complex128, error)

func (SliceAny) AsComplex64 added in v0.7.0

func (s SliceAny) AsComplex64(i int) (complex64, error)

func (SliceAny) AsDict added in v0.7.0

func (s SliceAny) AsDict(i int) (Dict, error)

func (SliceAny) AsDictAny added in v0.7.0

func (s SliceAny) AsDictAny(i int) (DictAny, error)

func (SliceAny) AsDuration added in v0.7.0

func (s SliceAny) AsDuration(i int) (time.Duration, error)

func (SliceAny) AsFloat32 added in v0.7.0

func (s SliceAny) AsFloat32(i int) (float32, error)

func (SliceAny) AsFloat64 added in v0.7.0

func (s SliceAny) AsFloat64(i int) (float64, error)

func (SliceAny) AsInt added in v0.7.0

func (s SliceAny) AsInt(i int) (int, error)

func (SliceAny) AsInt16 added in v0.7.0

func (s SliceAny) AsInt16(i int) (int16, error)

func (SliceAny) AsInt32 added in v0.7.0

func (s SliceAny) AsInt32(i int) (int32, error)

func (SliceAny) AsInt64 added in v0.7.0

func (s SliceAny) AsInt64(i int) (int64, error)

func (SliceAny) AsInt8 added in v0.7.0

func (s SliceAny) AsInt8(i int) (int8, error)

func (SliceAny) AsMap added in v0.7.0

func (s SliceAny) AsMap(i int) (Map, error)

func (SliceAny) AsMapAny added in v0.7.0

func (s SliceAny) AsMapAny(i int) (MapAny, error)

func (SliceAny) AsSlice added in v0.7.0

func (s SliceAny) AsSlice(i int) (Slice, error)

func (SliceAny) AsSliceAny added in v0.7.0

func (s SliceAny) AsSliceAny(i int) (SliceAny, error)

func (SliceAny) AsString added in v0.7.0

func (s SliceAny) AsString(i int) (string, error)

func (SliceAny) AsTime added in v0.7.0

func (s SliceAny) AsTime(i int) (time.Time, error)

func (SliceAny) AsUint added in v0.7.0

func (s SliceAny) AsUint(i int) (uint, error)

func (SliceAny) AsUint16 added in v0.7.0

func (s SliceAny) AsUint16(i int) (uint16, error)

func (SliceAny) AsUint32 added in v0.7.0

func (s SliceAny) AsUint32(i int) (uint32, error)

func (SliceAny) AsUint64 added in v0.7.0

func (s SliceAny) AsUint64(i int) (uint64, error)

func (SliceAny) AsUint8 added in v0.7.0

func (s SliceAny) AsUint8(i int) (uint8, error)

func (SliceAny) AsUintPtr added in v0.7.0

func (s SliceAny) AsUintPtr(i int) (uintptr, error)

func (SliceAny) BoolOr added in v0.7.0

func (s SliceAny) BoolOr(i int, fallback bool) bool

func (SliceAny) Complex128Or added in v0.7.0

func (s SliceAny) Complex128Or(i int, fallback complex128) complex128

func (SliceAny) Complex64Or added in v0.7.0

func (s SliceAny) Complex64Or(i int, fallback complex64) complex64

func (SliceAny) DaQGet added in v0.4.1

func (s SliceAny) DaQGet(i int) (Result, error)

func (SliceAny) DaQLen added in v0.4.1

func (s SliceAny) DaQLen() int

func (SliceAny) DurationOr added in v0.7.0

func (s SliceAny) DurationOr(i int, fallback time.Duration) time.Duration

func (SliceAny) Float32Or added in v0.7.0

func (s SliceAny) Float32Or(i int, fallback float32) float32

func (SliceAny) Float64Or added in v0.7.0

func (s SliceAny) Float64Or(i int, fallback float64) float64

func (SliceAny) Get added in v0.6.0

func (s SliceAny) Get(index int) (Result, error)

func (SliceAny) Int16Or added in v0.7.0

func (s SliceAny) Int16Or(i int, fallback int16) int16

func (SliceAny) Int32Or added in v0.7.0

func (s SliceAny) Int32Or(i int, fallback int32) int32

func (SliceAny) Int64Or added in v0.7.0

func (s SliceAny) Int64Or(i int, fallback int64) int64

func (SliceAny) Int8Or added in v0.7.0

func (s SliceAny) Int8Or(i int, fallback int8) int8

func (SliceAny) IntOr added in v0.7.0

func (s SliceAny) IntOr(i, fallback int) int

func (SliceAny) StringOr added in v0.7.0

func (s SliceAny) StringOr(i int, fallback string) string

func (SliceAny) TimeOr added in v0.7.0

func (s SliceAny) TimeOr(i int, fallback time.Time) time.Time

func (SliceAny) Uint16Or added in v0.7.0

func (s SliceAny) Uint16Or(i int, fallback uint16) uint16

func (SliceAny) Uint32Or added in v0.7.0

func (s SliceAny) Uint32Or(i int, fallback uint32) uint32

func (SliceAny) Uint64Or added in v0.7.0

func (s SliceAny) Uint64Or(i int, fallback uint64) uint64

func (SliceAny) Uint8Or added in v0.7.0

func (s SliceAny) Uint8Or(i int, fallback uint8) uint8

func (SliceAny) UintOr added in v0.7.0

func (s SliceAny) UintOr(i int, fallback uint) uint

func (SliceAny) UintPtrOr added in v0.7.0

func (s SliceAny) UintPtrOr(i int, fallback uintptr) uintptr

type StepError

type StepError struct {
	N    int
	Step any
	Err  error
}

func (StepError) Error

func (e StepError) Error() string

func (StepError) Unwrap

func (e StepError) Unwrap() error

type Stepper

type Stepper interface {
	// res.OK() => err == nil
	Step(data any) (res Result, err error)
}

Stepper allows to define how Step does the step from a data value to an element value. Implement Stepper for your own strategy to navigate your data.

type Time

type Time []string
Example
data := struct {
	Time string
}{
	Time: "2023-12-29T22:04:00Z",
}
// Asserting time.Time needs parsing, so we use Time() to create a parsing assertion
fmt.Println(Fallback(Time{time.RFC3339}.To, time.Time{})(Get(data, "Time")))
fmt.Println(Fallback(Time{time.RFC3339}.To, time.Time{})(Get(data, "void")))
Output:

2023-12-29 22:04:00 +0000 UTC
0001-01-01 00:00:00 +0000 UTC

func (Time) To added in v0.4.1

func (t Time) To(v any) (time.Time, error)

Convert function producing time.Time that also uses time.Parse() with layout t when v is string or fmt.Stringer. Otherwise it converts like ToTime.

type Track

type Track struct {
	T []any
	// contains filtered or unexported fields
}

func GetTrack

func GetTrack(data any, path ...any) (t Track, err error)

GetTrack is like Get but additionally returns all intermediate results on the path.

func (Track) Missed added in v0.7.0

func (t Track) Missed() int

func (Track) OK added in v0.7.0

func (t Track) OK() bool

func (Track) SplitPath added in v0.7.0

func (t Track) SplitPath(p []any) (done, missing []any)

func (Track) Step added in v0.5.0

func (t Track) Step(i int) any

Jump to

Keyboard shortcuts

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