From dec5ff2f981c605f9aebb358305c96ddbab44de0 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Tue, 19 Dec 2023 22:02:02 +0100 Subject: [PATCH 1/4] docs: fix readme Signed-off-by: Mark Sagi-Kazar --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 811b38c4..2b28db89 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,6 @@ structure. ## Installation -For the time being, you can use this library as a drop-in replacement for the original library: - ```shell go get github.com/go-viper/mapstructure/v2 ``` From aa4339df2d463da48ef4bb74d141ae49b69bc602 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Fri, 22 Dec 2023 15:31:58 +0100 Subject: [PATCH 2/4] docs: add migration guide Signed-off-by: Mark Sagi-Kazar --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index 2b28db89..45e6ad76 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,27 @@ structure. go get github.com/go-viper/mapstructure/v2 ``` +## Migrating from `github.com/mitchellh/mapstructure` + +[@mitchehllh](https://github.com/mitchellh) announced his intent to archive some of his unmaintained projects (see [here](https://gist.github.com/mitchellh/90029601268e59a29e64e55bab1c5bdc) and [here](https://github.com/mitchellh/mapstructure/issues/349)). This is a repository achieved the "blessed fork" status. + +You can migrate to this package by changing your import paths in your Go files to `github.com/go-viper/mapstructure/v2`. +The API is the same, so you don't need to change anything else. + +Here is a script that can help you with the migration: + +```shell +sed -i 's/github.com\/mitchellh\/mapstructure/github.com\/go-viper\/mapstructure\/v2/g' $(find . -type f -name '*.go') +``` + +If you need more time to migrate your code, that is absolutely fine. + +Some of the latest fixes are backported to the v1 release branch of this package, so you can use the Go modules `replace` feature until you are ready to migrate: + +```shell +The repository will not go away and will only be archived +``` + ## Usage & Example For usage and examples see the [documentation](https://pkg.go.dev/mod/github.com/go-viper/mapstructure/v2). From e909e757e1046036b01c0d5f6ada14ed4f26422f Mon Sep 17 00:00:00 2001 From: Carlo Hamalainen Date: Sat, 30 Dec 2023 19:52:23 +1000 Subject: [PATCH 3/4] Add an example showing how to use a DecodeHookFunc to parse a custom field. --- mapstructure_examples_test.go | 68 +++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/mapstructure_examples_test.go b/mapstructure_examples_test.go index 3880895a..539f290c 100644 --- a/mapstructure_examples_test.go +++ b/mapstructure_examples_test.go @@ -2,6 +2,9 @@ package mapstructure import ( "fmt" + "reflect" + "strconv" + "strings" ) func ExampleDecode() { @@ -289,3 +292,68 @@ func ExampleDecode_omitempty() { // Output: // &map[Age:0 FirstName:Somebody] } + +func ExampleDecode_decodeHookFunc() { + type PersonLocation struct { + Latitude float64 + Longtitude float64 + } + + type Person struct { + Name string + Location PersonLocation + } + + // Example of parsing messy input: here we have latitude, longitude squashed into + // a single string field. We write a custom DecodeHookFunc to parse the '#' separated + // values into a PersonLocation struct. + input := map[string]interface{}{ + "name": "Mitchell", + "location": "-35.2809#149.1300", + } + + toPersonLocationHookFunc := func() DecodeHookFunc { + return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + if t != reflect.TypeOf(PersonLocation{}) { + return data, nil + } + + switch f.Kind() { + case reflect.String: + xs := strings.Split(data.(string), "#") + + if len(xs) == 2 { + lat, errLat := strconv.ParseFloat(xs[0], 64) + lon, errLon := strconv.ParseFloat(xs[1], 64) + + if errLat == nil && errLon == nil { + return PersonLocation{Latitude: lat, Longtitude: lon}, nil + } + } else { + return data, nil + } + } + return data, nil + } + } + + var result Person + + decoder, errDecoder := NewDecoder(&DecoderConfig{ + Metadata: nil, + DecodeHook: toPersonLocationHookFunc(), // Here, use ComposeDecodeHookFunc to run multiple hooks. + Result: &result, + }) + if errDecoder != nil { + panic(errDecoder) + } + + err := decoder.Decode(input) + if err != nil { + panic(err) + } + + fmt.Printf("%#v", result) + // Output: + // mapstructure.Person{Name:"Mitchell", Location:mapstructure.PersonLocation{Latitude:-35.2809, Longtitude:149.13}} +} From 259066293f1aa44a1bc2f17b02dfc8d585de5335 Mon Sep 17 00:00:00 2001 From: Carlo Hamalainen Date: Tue, 27 Feb 2024 15:48:35 +0800 Subject: [PATCH 4/4] Run golangci-lint --- mapstructure_examples_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mapstructure_examples_test.go b/mapstructure_examples_test.go index 539f290c..31cff15d 100644 --- a/mapstructure_examples_test.go +++ b/mapstructure_examples_test.go @@ -300,7 +300,7 @@ func ExampleDecode_decodeHookFunc() { } type Person struct { - Name string + Name string Location PersonLocation } @@ -308,7 +308,7 @@ func ExampleDecode_decodeHookFunc() { // a single string field. We write a custom DecodeHookFunc to parse the '#' separated // values into a PersonLocation struct. input := map[string]interface{}{ - "name": "Mitchell", + "name": "Mitchell", "location": "-35.2809#149.1300", } @@ -340,9 +340,9 @@ func ExampleDecode_decodeHookFunc() { var result Person decoder, errDecoder := NewDecoder(&DecoderConfig{ - Metadata: nil, + Metadata: nil, DecodeHook: toPersonLocationHookFunc(), // Here, use ComposeDecodeHookFunc to run multiple hooks. - Result: &result, + Result: &result, }) if errDecoder != nil { panic(errDecoder)