From ef74c148e25c0a49172d7e8b1513911331ae79b4 Mon Sep 17 00:00:00 2001 From: Kuisong Tong Date: Sun, 7 Jan 2024 03:35:44 -0800 Subject: [PATCH] Switch from mitchellh/mapstructure to go-viper/mapstructure (#69) Reference: https://github.com/mitchellh/mapstructure/issues/349#issuecomment-1860372162 mitchellh stops the maintenance for [mapstructure](https://github.com/mitchellh/mapstructure) and other https://github.com/mitchellh/mapstructure/issues/349#issuecomment-1859202291. The mapstructure project is already forked by viper project, since they have a strong dependency against it. https://github.com/go-viper/mapstructure --- CHANGELOG.md | 4 +++ config.go | 74 ++-------------------------------------------------- go.mod | 2 +- go.sum | 4 +-- option.go | 2 +- 5 files changed, 10 insertions(+), 76 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0606baa..b2f8ec39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Changed + +- Switch from mitchellh/mapstructure to go-viper/mapstructure (#69). + ## [v0.3.0] - 11/17/2023 ### Changed diff --git a/config.go b/config.go index 682f1b1a..f0931fd9 100644 --- a/config.go +++ b/config.go @@ -5,15 +5,13 @@ package konf import ( "context" - "encoding" "errors" "fmt" "log/slog" - "reflect" "strings" "sync" - "github.com/mitchellh/mapstructure" + "github.com/go-viper/mapstructure/v2" "github.com/ktong/konf/internal/maps" ) @@ -47,7 +45,7 @@ func New(opts ...Option) *Config { decodeHook: mapstructure.ComposeDecodeHookFunc( mapstructure.StringToTimeDurationHookFunc(), mapstructure.StringToSliceHookFunc(","), - textUnmarshalerHookFunc(), + mapstructure.TextUnmarshallerHookFunc(), ), values: make(map[string]any), onChanges: make(map[string][]func(*Config)), @@ -257,71 +255,3 @@ func (c *Config) Unmarshal(path string, target any) error { return nil } - -// textUnmarshalerHookFunc is a fixed version of mapstructure.TextUnmarshallerHookFunc. -// This hook allows to additionally unmarshal text into custom string types -// that implement the encoding.Text(Un)Marshaler interface(s). -// -//nolint:wrapcheck -func textUnmarshalerHookFunc() mapstructure.DecodeHookFuncType { - return func( - from reflect.Type, - to reflect.Type, //nolint:varnamelen - data interface{}, - ) (interface{}, error) { - if from.Kind() != reflect.String { - return data, nil - } - result := reflect.New(to).Interface() - unmarshaller, ok := result.(encoding.TextUnmarshaler) - if !ok { - return data, nil - } - - // default text representation is the actual value of the `from` string - var ( - dataVal = reflect.ValueOf(data) - text = []byte(dataVal.String()) - ) - if from.Kind() == to.Kind() { //nolint:nestif - // source and target are of underlying type string - var ( - err error - ptrVal = reflect.New(dataVal.Type()) - ) - if !ptrVal.Elem().CanSet() { - // cannot set, skip, this should not happen - if err := unmarshaller.UnmarshalText(text); err != nil { - return nil, err - } - - return result, nil - } - ptrVal.Elem().Set(dataVal) - - // We need to assert that both, the value type and the pointer type - // do (not) implement the TextMarshaller interface before proceeding and simply - // using the string value of the string type. - // it might be the case that the internal string representation differs from - // the (un)marshaled string. - for _, v := range []reflect.Value{dataVal, ptrVal} { - if marshaller, ok := v.Interface().(encoding.TextMarshaler); ok { - text, err = marshaller.MarshalText() - if err != nil { - return nil, err - } - - break - } - } - } - - // text is either the source string's value or the source string type's marshaled value - // which may differ from its internal string value. - if err := unmarshaller.UnmarshalText(text); err != nil { - return nil, err - } - - return result, nil - } -} diff --git a/go.mod b/go.mod index 63f8d7da..d7da430a 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,4 @@ module github.com/ktong/konf go 1.21 -require github.com/mitchellh/mapstructure v1.5.0 +require github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 diff --git a/go.sum b/go.sum index 59f4b8e6..aa920064 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,2 @@ -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= diff --git a/option.go b/option.go index c9513c30..6466696c 100644 --- a/option.go +++ b/option.go @@ -3,7 +3,7 @@ package konf -import "github.com/mitchellh/mapstructure" +import "github.com/go-viper/mapstructure/v2" // WithDelimiter provides the delimiter used when specifying config paths. // The delimiter is used to separate keys in the path.