My app takes a JSON string, unmarshal into a struct BiggerType
and then, decode the struct’s field Settings
into a type MainType
. BiggerType
needs to support multiple types of Settings
and hence, is and has to be declared as map[string]interface{}
. The app used to be working fine until we have a new type of Settings
, i.e. MainType
containing some custom fields with the type SpecialType
.
The structs and the main codes are included below. Running the code gives the following error.
* 'b' expected a map, got 'string'
Some codes were removed for brevity
package main
import (
...
"github.com/mitchellh/mapstructure"
)
const myJSON = `{
"settings": {
"a": {
"aa": {
"aaa": {
"sta": "special_object_A",
"stb": "special_object_B"
},
"aab": "bab"
},
"ab": true
},
"b": "special_string"
},
"other": "other"
}`
func main() {
var biggerType BiggerType
err := json.Unmarshal([]byte(myJSON), &biggerType)
if err != nil {
panic(err)
}
var decodedMainType MainType
if err := mapstructure.Decode(biggerType.Settings, &decodedMainType); err != nil {
panic(err)
}
}
type BiggerType struct {
Other string `json:"other"`
// Settings MainType `json:"settings"` can't be used as it needs to support other "Settings"
Settings map[string]interface{} `json:"settings"`
}
type A struct {
Aa *AA `json:"aa"`
Ab *bool `json:"ab"`
}
type AA struct {
Aaa SpecialType `json:"aaa"`
Aab string `json:"aab"`
}
type MainType struct {
A A `json:"a"`
B SpecialType `json:"b"`
}
type SpecialTypeObject struct {
Sta string `json:"sta"`
Stb string `json:"stb"`
}
func (s SpecialTypeObject) InterfaceMethod() (string, error) {
return s.Sta + "+" + s.Stb, nil
}
type SpecialTypeString string
func (s SpecialTypeString) InterfaceMethod() (string, error) {
return string(s), nil
}
type SpecialInterface interface {
InterfaceMethod() (string, error)
}
// SpecialType SpecialTypeString | SpecialTypeObject
type SpecialType struct {
Value SpecialInterface
}
func (s *SpecialType) UnmarshalJSON(data []byte) error {
...
}
My goal is to be able to decode biggerType.Settings
into decodedMainType
with all the values intact. Can anyone please share with me any workaround or/and suggestions?
The playground to replicate the issue: Go Playground - The Go Programming Language
Thank you.