Reputation: 2886
I got a map[string]interface{} because decoding to JSON; with normal data, interface most be only a number but in type string, like this :
var a interface{}
a="3"
And then all data will be stored into a struct.
type someStruct struct {
ID string
Number1 int
Number2 int
Number3 int
Number4 int
}
So I need to convert interface to int, but can´t do it easily and efficiently because only the code would be https://play.golang.org/p/oktbvTUbk93, pretty annoying and code does not seem to be readable if you take in mind the fact that I should handle all of possible errors
I would want to convert it directly to int, I´ve been searching for solutions but any of this convertions works as I want https://play.golang.org/p/Dw67U6kZwHC
In case you wondering why I don´t just decode it into struct directly, it´s because it´s dynamic data, the actual decoding occurs like this :
type dataIn struct {
Code int `json:"code"`
ID string `json:"id"`
Data interface{} `json:"data"`
}
And then I handle Data according to code and id, and they all are different data structures, so I can´t directly handle it with JSON
Upvotes: 0
Views: 6362
Reputation: 417797
Create a helper function which does parsing and validating for you, in one place:
func parseInt(i interface{}) (int, error) {
s, ok := i.(string)
if !ok {
return 0, errors.New("not string")
}
return strconv.Atoi(s)
}
And you can use this where needed. Here's a complete example, in which I also used another helper function, which takes care of the error handling:
m := map[string]interface{}{
"number1": "1",
"number2": "2",
"number3": "3",
"number4": "4",
"ID": "asdsa",
"Title": "asdas",
}
getInt := func(key string) int {
n, err := parseInt(m[key])
if err != nil {
panic(err) // Decide what you wanna do with error
}
return n
}
// converting to struct
data := element{
ID: m["ID"].(string),
Title: m["Title"].(string),
Number1: getInt("number1"),
Number2: getInt("number2"),
Number3: getInt("number3"),
Number4: getInt("number4"),
}
fmt.Printf("%+v\n", data)
Output of the above (try it on the Go Playground):
{ID:asdsa Title:asdas Number1:1 Number2:2 Number3:3 Number4:4}
Also note that the open source package github.com/icza/dyno
should help you handle dynamic objects at ease. (Disclosure: I'm the author.) It has a dyno.GetInteger()
function for example, which is capable of extracting an int64
value out of multiple types (such as integers, floats, strings etc.).
Upvotes: 3
Reputation: 20
I still didn't get the part where you stated the struct is generated dynamically. Anyways, you can have a struct method attached, that does the int conversion. If the Data
field, which is of type interface{}
is always gonna hold integers, you an try this:
type DataIn struct {
Code int `json:"code"`
ID string `json:"id"`
Data interface{} `json:"data"`
}
func (s DataIn) toInt() int {
switch t := s.Data.(type)
case int:
i, _ := strings.Atoi(fmt.Sprintf("%v",s.Data))
return i
}
// using it
sampleData := someStruct{
Number1: datain.toInt(),
}
Upvotes: 0
Reputation: 4109
Sounds like what you need is a custom unmarshal json method on your main struct. First, unmarshal into your main struct to get your code and id, then use those in a switch statement to determine which struct to use for the rest of the data and unmarshal into that, stirring that struct in your Data field.
Upvotes: 0