The empty interface (interface{}), and its variants (such as []interface{} and map[string]interface{}), are commonly used in Go to (json) Unmarshal arbitrary data. Within Yaegi, all interface types are wrapped in a valueInterface struct in order to retain all the information needed for a consistent internal state (as reflect is not enough to achieve that). However, this wrapping ends up being problematic when it comes to the type assertions related to the aforementioned Unmarshaling.
Therefore, this PR is an attempt to consider the empty interface (and its variants) as an exception within Yaegi, that should never be wrapped within a valueInterface, and to treat it similarly to the other basic Go types. The assumption is that the wrapping should not be needed, as there is no information about implemented methods to maintain.
Fixes #984
Fixes #829
Fixes #1015
63 lines
1.1 KiB
Go
63 lines
1.1 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/url"
|
|
)
|
|
|
|
func main() {
|
|
body := []byte(`{
|
|
"BODY_1": "VALUE_1",
|
|
"BODY_2": "VALUE_2",
|
|
"BODY_3": null,
|
|
"BODY_4": {
|
|
"BODY_1": "VALUE_1",
|
|
"BODY_2": "VALUE_2",
|
|
"BODY_3": null
|
|
},
|
|
"BODY_5": [
|
|
"VALUE_1",
|
|
"VALUE_2",
|
|
"VALUE_3"
|
|
]
|
|
}`)
|
|
|
|
values := url.Values{}
|
|
|
|
var rawData map[string]interface{}
|
|
err := json.Unmarshal(body, &rawData)
|
|
if err != nil {
|
|
fmt.Println("can't parse body")
|
|
return
|
|
}
|
|
|
|
for key, val := range rawData {
|
|
switch val.(type) {
|
|
case string, bool, float64:
|
|
values.Add(key, fmt.Sprint(val))
|
|
case nil:
|
|
values.Add(key, "")
|
|
case map[string]interface{}, []interface{}:
|
|
jsonVal, err := json.Marshal(val)
|
|
if err != nil {
|
|
fmt.Println("can't encode json")
|
|
return
|
|
}
|
|
values.Add(key, string(jsonVal))
|
|
}
|
|
}
|
|
fmt.Println(values.Get("BODY_1"))
|
|
fmt.Println(values.Get("BODY_2"))
|
|
fmt.Println(values.Get("BODY_3"))
|
|
fmt.Println(values.Get("BODY_4"))
|
|
fmt.Println(values.Get("BODY_5"))
|
|
}
|
|
|
|
// Output:
|
|
// VALUE_1
|
|
// VALUE_2
|
|
//
|
|
// {"BODY_1":"VALUE_1","BODY_2":"VALUE_2","BODY_3":null}
|
|
// ["VALUE_1","VALUE_2","VALUE_3"]
|