reflection

package
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Jul 4, 2019 License: BSD-3-Clause Imports: 5 Imported by: 3

Documentation

Overview

Package reflection provides GetStructFields, allowing for the collection of structural information about structs or maps.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AliasedKey

type AliasedKey []AliasedKeyElem

AliasedKey is a key that can be written multiple ways, all of which should match. Each element may have aliases. None of the elements will be empty.

func (AliasedKey) Equal

func (ak AliasedKey) Equal(cmp AliasedKey) bool

Equal returns true if the two AliasedKeys match.

func (AliasedKey) HasPrefix

func (ak AliasedKey) HasPrefix(prefix AliasedKey) bool

HasPrefix returns true if prefix is a prefix of the key (or equal to it).

type AliasedKeyElem

type AliasedKeyElem []string

AliasedKeyElem is one component of an aliased key. Contains equivalent aliases for this component.

Guarantee: The struct tag alias will be last.

func (AliasedKeyElem) Equal

func (ake AliasedKeyElem) Equal(cmp AliasedKeyElem) bool

Equal returns true if the two AliasedKeyElems match.

type Codec

type Codec interface {
	// Returns true if the struct tag indicates that the field is not unmarshaled (like `json:"-"`)
	IsStructFieldIgnored(st reflect.StructTag) bool

	// Returns the alias name of the field from the struct tag (like `json:"new_name"`)
	// or empty string if the field has no alias
	GetStructFieldAlias(st reflect.StructTag) string
}

Codec is an interface which must be implemented and passed to GetStructFields. It provides abstraction for the underlying config file type (like TOML or JSON).

type StructField

type StructField struct {
	// The key for the field within the struct (including possible aliase due to struct tags)
	AliasedKey AliasedKey

	// true if the field has been flagged as optional in the struct tag; false otherwise.
	Optional bool

	// reflect's Type() for the field. Like "time.Time".
	Type string
	// reflect's Kind() for the field. Like "struct".
	Kind string

	// If the strut tag contains an explicit type, it will be provided here.
	ExpectedType string

	// Pointer to the parent of the field (for non-roots)
	Parent *StructField
	// Pointers to the children of this field (for non-leafs)
	Children []*StructField
}

StructField holds information about field in a struct.

func GetStructFields

func GetStructFields(obj interface{}, tagName string, codec Codec) []*StructField

GetStructFields returns information about the structure of obj. It can be passed either a struct or a map. The non-exported fields of a struct are ignored.

tagName is the struct tag name that will be used to flag whether a field is optional and if there is an explicit type that should be associated with it.

codec implements Codec and is used to determine if fields have an alias or should be ignored. (I.e., with the `json:` or `toml:` struct tags.)

The returned slice is guaranteed to have branches before leaves.

Example (WithMap)
package main

import (
	"fmt"
	"time"

	"github.com/Psiphon-Inc/configloader-go/reflection"
	"github.com/Psiphon-Inc/configloader-go/toml"
)

func main() {
	const tagName = "conf"

	m := map[string]interface{}{
		"a": "aaa",
		"b": 123,
		"c": time.Now(),
		"d": map[string]interface{}{
			"d1": "d1d1",
		},
		"e": []bool{true, false},
	}

	structFields := reflection.GetStructFields(m, tagName, toml.Codec)

	for _, sf := range structFields {
		fmt.Println(sf)
	}

}
Output:

StructField{
	AliasedKey: [[a]]
	Optional: false
	Type: string
	Kind: string
	ExpectedType:
	Parent: nil
	Children: {}
}
StructField{
	AliasedKey: [[b]]
	Optional: false
	Type: int
	Kind: int
	ExpectedType:
	Parent: nil
	Children: {}
}
StructField{
	AliasedKey: [[c]]
	Optional: false
	Type: time.Time
	Kind: struct
	ExpectedType: string
	Parent: nil
	Children: {}
}
StructField{
	AliasedKey: [[d]]
	Optional: false
	Type: map[string]interface {}
	Kind: map
	ExpectedType:
	Parent: nil
	Children: {
		[[d] [d1]]
	}
}
StructField{
	AliasedKey: [[d] [d1]]
	Optional: false
	Type: string
	Kind: string
	ExpectedType:
	Parent: [[d]]
	Children: {}
}
StructField{
	AliasedKey: [[e]]
	Optional: false
	Type: []bool
	Kind: slice
	ExpectedType:
	Parent: nil
	Children: {}
}
Example (WithStruct)
package main

import (
	"fmt"
	"time"

	"github.com/Psiphon-Inc/configloader-go/reflection"
	"github.com/Psiphon-Inc/configloader-go/toml"
)

func main() {
	const tagName = "conf"

	type S struct {
		F     string `toml:"eff" conf:"optional"`
		Inner struct {
			InnerF int
		}
		Time time.Time // implements encoding.UnmarshalText

		unexported string
	}

	var s S
	structFields := reflection.GetStructFields(s, tagName, toml.Codec)

	for _, sf := range structFields {
		fmt.Println(sf)
	}

}
Output:

StructField{
	AliasedKey: [[F eff]]
	Optional: true
	Type: string
	Kind: string
	ExpectedType:
	Parent: nil
	Children: {}
}
StructField{
	AliasedKey: [[Inner]]
	Optional: false
	Type: struct { InnerF int }
	Kind: struct
	ExpectedType:
	Parent: nil
	Children: {
		[[Inner] [InnerF]]
	}
}
StructField{
	AliasedKey: [[Inner] [InnerF]]
	Optional: false
	Type: int
	Kind: int
	ExpectedType:
	Parent: [[Inner]]
	Children: {}
}
StructField{
	AliasedKey: [[Time]]
	Optional: false
	Type: time.Time
	Kind: struct
	ExpectedType: string
	Parent: nil
	Children: {}
}

func (StructField) String

func (sf StructField) String() string

String is intended to be used for making example output more readable.

Jump to

Keyboard shortcuts

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