mapstructurex

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Aug 15, 2023 License: MIT Imports: 3 Imported by: 0

README

Extensions for mapstructure

GitHub Workflow Status go.dev reference Go Version built with nix

Installation

go get github.com/sagikazarmark/mapstructurex

Development

For an optimal developer experience, it is recommended to install Nix and direnv.

Run the test suite:

just test

License

The project is licensed under the MIT License.

Documentation

Overview

Package mapstructurex contains various extensions (primarily decoding hooks) to mapstructure.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func MapDecoderHookFunc

func MapDecoderHookFunc() mapstructure.DecodeHookFunc

MapDecoderHookFunc returns a mapstructure.DecodeHookFunc that applies maps to the DecodeMap function, when the target type implements the MapDecoder interface.

Example
package main

import (
	"fmt"

	"github.com/mitchellh/mapstructure"

	"github.com/sagikazarmark/mapstructurex"
)

type Person struct {
	Name string
	Age  int
}

func (p *Person) DecodeMap(v map[string]any) error {
	type alias Person

	var result alias

	decoder, err := CreateDecoderWithMapDecoderHook(&result)
	if err != nil {
		return err
	}

	err = decoder.Decode(v)
	if err != nil {
		return err
	}

	*p = Person(result)

	return nil
}

func (p Person) String() string {
	return fmt.Sprintf("%s: %d", p.Name, p.Age)
}

func CreateDecoderWithMapDecoderHook(result any) (*mapstructure.Decoder, error) {
	return mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		DecodeHook: mapstructurex.MapDecoderHookFunc(),
		Metadata:   nil,
		Result:     result,
	})
}

func main() {
	var person Person

	decoder, _ := CreateDecoderWithMapDecoderHook(&person)

	input := map[string]any{
		"name": "Bob",
		"age":  42,
	}

	_ = decoder.Decode(input)

	fmt.Println(person)
}
Output:

Bob: 42
Example (Polymorphic)
package main

import (
	"errors"
	"fmt"

	"github.com/mitchellh/mapstructure"

	"github.com/sagikazarmark/mapstructurex"
)

func CreateDecoderWithMapDecoderHook(result any) (*mapstructure.Decoder, error) {
	return mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		DecodeHook: mapstructurex.MapDecoderHookFunc(),
		Metadata:   nil,
		Result:     result,
	})
}

// Config is a struct that implements a custom decoding function.
// The embedded [Fooer] interface provides polymorphism.
// Alternative implementations of [Fooer] can provide different configurations.
type Config struct {
	Fooer
}

// Fooer is an interface that provides polymorphism for [Config].
type Fooer interface {
	Foo() string
}

// RawConfig mimics the structure of configuration (for example in a config file).
// Type determines the [Fooer] implementation, Config is the input for the implementation.
type RawConfig struct {
	Type   string
	Config map[string]any
}

func (c *Config) DecodeMap(v map[string]any) error {
	var rawConfig RawConfig

	err := mapstructure.Decode(v, &rawConfig)
	if err != nil {
		return err
	}

	switch rawConfig.Type {
	case "bar":
		var bar ConfigBar
		err := mapstructure.Decode(rawConfig.Config, &bar)
		if err != nil {
			return err
		}
		c.Fooer = bar
	case "baz":
		var baz ConfigBaz
		err := mapstructure.Decode(rawConfig.Config, &baz)
		if err != nil {
			return err
		}
		c.Fooer = baz
	default:
		return errors.New("unknown type")

	}

	return nil
}

// ConfigBar is a [Fooer].
type ConfigBar struct {
	Bar string
}

func (c ConfigBar) Foo() string {
	return c.Bar
}

// ConfigBaz is a [Fooer].
type ConfigBaz struct {
	Baz string
}

func (c ConfigBaz) Foo() string {
	return c.Baz
}

func main() {
	var config Config

	decoder, _ := CreateDecoderWithMapDecoderHook(&config)

	input := map[string]any{
		"type": "baz",
		"config": map[string]any{
			"baz": "bat",
		},
	}

	err := decoder.Decode(input)
	if err != nil {
		panic(err)
	}

	fmt.Println(config.Foo())
}
Output:

bat

func StringToNetIPAddrHookFunc

func StringToNetIPAddrHookFunc() mapstructure.DecodeHookFunc

StringToNetIPAddrHookFunc returns a mapstructure.DecodeHookFunc that converts strings to netip.Addr.

Will be removed once https://github.com/mitchellh/mapstructure/pull/315 is merged.

func StringToNetIPAddrPortHookFunc

func StringToNetIPAddrPortHookFunc() mapstructure.DecodeHookFunc

StringToNetIPAddrPortHookFunc returns a mapstructure.DecodeHookFunc that converts strings to netip.AddrPort.

Will be removed once https://github.com/mitchellh/mapstructure/pull/315 is merged.

Types

type MapDecoder

type MapDecoder interface {
	DecodeMap(map[string]any) error
}

MapDecoder is the interface implemented by an object that can decode a raw map representation of itself.

Jump to

Keyboard shortcuts

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