I'm trying to get a value from a JSON and cast it to int but it doesn't work, and I don't know how to do it properly.
Here is the error message:
...cannot convert val (type interface {}) to type int: need type assertion
And the code:
var f interface{}
err = json.Unmarshal([]byte(jsonStr), &f)
if err != nil {
utility.CreateErrorResponse(w, "Error: failed to parse JSON data.")
return
}
m := f.(map[string]interface{})
val, ok := m["area_id"]
if !ok {
utility.CreateErrorResponse(w, "Error: Area ID is missing from submitted data.")
return
}
fmt.Fprintf(w, "Type = %v", val) // <--- Type = float64
iAreaId := int(val) // <--- Error on this line.
testName := "Area_" + iAreaId // not reaching here
This question is related to
go
I am assuming: If you sent the JSON value through browser then any number you sent that will be the type float64 so you cant get the value directly int in golang.
So do the conversion like:
//As that says:
fmt.Fprintf(w, "Type = %v", val) // <--- Type = float64
var iAreaId int = int(val.(float64))
This way you can get exact value what you wanted.
Adding another answer that uses switch
... There are more comprehensive examples out there, but this will give you the idea.
In example, t
becomes the specified data type within each case
scope. Note, you have to provide a case
for only one type at a type, otherwise t
remains an interface
.
package main
import "fmt"
func main() {
var val interface{} // your starting value
val = 4
var i int // your final value
switch t := val.(type) {
case int:
fmt.Printf("%d == %T\n", t, t)
i = t
case int8:
fmt.Printf("%d == %T\n", t, t)
i = int(t) // standardizes across systems
case int16:
fmt.Printf("%d == %T\n", t, t)
i = int(t) // standardizes across systems
case int32:
fmt.Printf("%d == %T\n", t, t)
i = int(t) // standardizes across systems
case int64:
fmt.Printf("%d == %T\n", t, t)
i = int(t) // standardizes across systems
case bool:
fmt.Printf("%t == %T\n", t, t)
// // not covertible unless...
// if t {
// i = 1
// } else {
// i = 0
// }
case float32:
fmt.Printf("%g == %T\n", t, t)
i = int(t) // standardizes across systems
case float64:
fmt.Printf("%f == %T\n", t, t)
i = int(t) // standardizes across systems
case uint8:
fmt.Printf("%d == %T\n", t, t)
i = int(t) // standardizes across systems
case uint16:
fmt.Printf("%d == %T\n", t, t)
i = int(t) // standardizes across systems
case uint32:
fmt.Printf("%d == %T\n", t, t)
i = int(t) // standardizes across systems
case uint64:
fmt.Printf("%d == %T\n", t, t)
i = int(t) // standardizes across systems
case string:
fmt.Printf("%s == %T\n", t, t)
// gets a little messy...
default:
// what is it then?
fmt.Printf("%v == %T\n", t, t)
}
fmt.Printf("i == %d\n", i)
}
I wrote a library that can help with type convertions https://github.com/KromDaniel/jonson
js := jonson.New([]interface{}{55.6, 70.8, 10.4, 1, "48", "-90"})
js.SliceMap(func(jsn *jonson.JSON, index int) *jonson.JSON {
jsn.MutateToInt()
return jsn
}).SliceMap(func(jsn *jonson.JSON, index int) *jonson.JSON {
if jsn.GetUnsafeInt() > 50{
jsn.MutateToString()
}
return jsn
}) // ["55","70",10,1,48,-90]
Best avoid casting by declaring f to be f the correct type to correspond to the JSON.
I whole-heartedly agree with zzzz's type assertion answer and I strongly prefer that way over others. That said, here's what I've had to do when the preferred method has not worked... (long story related to cross-serialization of data). You can even chain this into a switch
statement with case errInt == nil
and similar expressions.
package main
import "fmt"
import "strconv"
func main() {
var v interface{}
v = "4"
i, errInt := strconv.ParseInt(v.(string), 10, 64)
if errInt == nil {
fmt.Printf("%d is a int", i)
/* do what you wish with "i" here */
}
}
Like I said above, try type assertion first before trying this way.
To better understand the type conversion, look at the code below:
package main
import "fmt"
func foo(a interface{}) {
fmt.Println(a.(int)) // conversion of interface into int
}
func main() {
var a int = 10
foo(a)
}
This code executes perfectly and converts interface type to int type
For an expression x of interface type and a type T, the primary expression x.(T) asserts that x is not nil and that the value stored in x is of type T. The notation x.(T) is called a type assertion. More precisely, if T is not an interface type, x.(T) asserts that the dynamic type of x is identical to the type T. In this case, T must implement the (interface) type of x; otherwise the type assertion is invalid since it is not possible for x to store a value of type T. If T is an interface type, x.(T) asserts that the dynamic type of x implements the interface T.
Going back to your code, this
iAreaId := val.(int)
should work good. If you want to check error occured while conversion, you can also re-write above line as
iAreaId, ok := val.(int)
You need to do type assertion for converting your interface{} to int value.
iAreaId := val.(int)
iAreaId, ok := val.(int)
More information is available.
Simplest way I did this. Not the best way but simplest way I know how.
import "fmt"
func main() {
fmt.Print(addTwoNumbers(5, 6))
}
func addTwoNumbers(val1 interface{}, val2 interface{}) int {
op1, _ := val1.(int)
op2, _ := val2.(int)
return op1 + op2
}
maybe you need
func TransToString(data interface{}) (res string) {
switch v := data.(type) {
case float64:
res = strconv.FormatFloat(data.(float64), 'f', 6, 64)
case float32:
res = strconv.FormatFloat(float64(data.(float32)), 'f', 6, 32)
case int:
res = strconv.FormatInt(int64(data.(int)), 10)
case int64:
res = strconv.FormatInt(data.(int64), 10)
case uint:
res = strconv.FormatUint(uint64(data.(uint)), 10)
case uint64:
res = strconv.FormatUint(data.(uint64), 10)
case uint32:
res = strconv.FormatUint(uint64(data.(uint32)), 10)
case json.Number:
res = data.(json.Number).String()
case string:
res = data.(string)
case []byte:
res = string(v)
default:
res = ""
}
return
}
Source: Stackoverflow.com