I'm reading data structures from JSON. There's a little bit of conversions going on and at the end I have a struct
where one of the fields is of type interface{}
. It's actually a map, so JSON puts it inside a map[string]inteface{}
.
I actually know that the underlying structure is map[string]float64
and I would like to use it like that, so I try to do an assertion. The following code reproduces the behaviour:
type T interface{}
func jsonMap() T {
result := map[string]interface{}{
"test": 1.2,
}
return T(result)
}
func main() {
res := jsonMap()
myMap := res.(map[string]float64)
fmt.Println(myMap)
}
I get the error:
panic: interface conversion: main.T is map[string]interface {}, not map[string]float64
I can do the following:
func main() {
// A first assertion
res := jsonMap().(map[string]interface{})
myMap := map[string]float64{
"test": res["test"].(float64), // A second assertion
}
fmt.Println(myMap)
}
This works fine, but I find it very ugly since I need to reconstruct the whole map and use two assertions. Is there a correct way to force the first assertion to drop the interface{}
and use float64
? In other words, what is the correct way to do the original assertion .(map[string]float64)
?
Edit:
The actual data I'm parsing looks like this:
[
{"Type":"pos",
"Content":{"x":0.5 , y: 0.3}} ,
{"Type":"vel",
"Content":{"vx": 0.1, "vy": -0.2}}
]
In Go I use a struct
and encoding/json
in the following way.
type data struct {
Type string
Content interface{}
}
// I read the JSON from a WebSocket connection
_, event, _ := c.ws.ReadMessage()
j := make([]data,0)
json.Unmarshal(event, &j)
Type assertion in Goi , which is the variable whose type we are asserting. This variable must be defined as an interface. type , which is the type we are asserting our variable is (such as string, int, float64, etc) t , which is a variable that stores the value of our variable i , if our type assertion is correct.
However, there is another way to do type assertion, using the 'as' syntax. let code: any = 123; let employeeCode = code as number; Both the syntaxes are equivalent and we can use any of these type assertions syntaxes.
Golang Maps is a collection of unordered pairs of key-value. It is widely used because it provides fast lookups and values that can retrieve, update or delete with the help of keys. It is a reference to a hash table.
Golang provides a simple way of checking if an interface value is of a specific type. This is called type assertion, and it is generally used to make sure that an interface value satisfies another interface or to find the concrete type of the interface.
You cannot type assert map[string]interface{}
to map[string]float64
. You need to manually create new map.
package main
import (
"encoding/json"
"fmt"
)
var exampleResponseData = `{
"Data":[
{
"Type":"pos",
"Content":{
"x":0.5,
"y":0.3
}
},
{
"Type":"vel",
"Content":{
"vx":0.1,
"vy":-0.2
}
}
]
}`
type response struct {
Data []struct {
Type string
Content interface{}
}
}
func main() {
var response response
err := json.Unmarshal([]byte(exampleResponseData), &response)
if err != nil {
fmt.Println("Cannot process not valid json")
}
for i := 0; i < len(response.Data); i++ {
response.Data[i].Content = convertMap(response.Data[i].Content)
}
}
func convertMap(originalMap interface{}) map[string]float64 {
convertedMap := map[string]float64{}
for key, value := range originalMap.(map[string]interface{}) {
convertedMap[key] = value.(float64)
}
return convertedMap
}
Are you sure you cannot define Content
as map[string]float64
? See example below. If not, how can you know that you can cast it in the first place?
type response struct {
Data []struct {
Type string
Content map[string]float64
}
}
var response response
err := json.Unmarshal([]byte(exampleResponseData), &response)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With