J'essaie d'obtenir une valeur d'un JSON et de la convertir en int, mais cela ne fonctionne pas et je ne sais pas comment le faire correctement.
Voici le message d'erreur:
...cannot convert val (type interface {}) to type int: need type assertion
Et le 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
Au lieu de
iAreaId := int(val)
vous voulez un type assertion :
iAreaId := val.(int)
iAreaId, ok := val.(int) // Alt. non panicking version
La raison pour laquelle vous ne pouvez pas convertir une valeur typée d'interface sont les suivantes:
Les conversions sont des expressions de la forme
T(x)
oùT
est un type etx
est une expression qui peut être convertie en type T.
...
Une valeur non constante x peut être convertie en type T dans l’un des cas suivants:
- x est assignable à T.
- le type de x et T ont des types sous-jacents identiques.
- le type de x et T sont des types de pointeur sans nom et leurs types de base de pointeur ont des types sous-jacents identiques.
- le type de x et T sont des types entiers ou à virgule flottante.
- le type de x et T sont deux types complexes.
- x est un entier ou une tranche d'octets ou de runes et T est un type de chaîne.
- x est une chaîne et T est une tranche d'octets ou de runes.
Mais
iAreaId := int(val)
est pas l’un des cas 1.-7.
Je suppose: si vous avez envoyé la valeur JSON via un navigateur, le nombre que vous avez envoyé sera du type float64, de sorte que vous ne pouvez pas obtenir la valeur directement en golang.
Alors faites la conversion comme:
//As that says:
fmt.Fprintf(w, "Type = %v", val) // <--- Type = float64
var iAreaId int = int(val.(float64))
De cette façon, vous pouvez obtenir une valeur exacte de ce que vous vouliez.
Je suis tout à fait d’accord avec la réponse de zzzz s type et je la préfère fortement aux autres. Cela dit, voici ce que j'ai dû faire lorsque la méthode préférée n'a pas fonctionné ... (histoire longue liée à la sérialisation croisée des données). Vous pouvez même chaîner cela dans une instruction switch
avec case errInt == nil
et des expressions similaires.
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 */
}
}
Comme je l'ai dit plus haut, essayez d'abord type assertion avant d'essayer de cette façon.
Ajouter une autre réponse qui utilise switch
... Il existe des exemples plus complets, mais cela vous en donnera l’idée.
Par exemple, t
devient le type de données spécifié dans chaque étendue case
. Notez que vous devez fournir une case
pour un seul type pour un type, sinon t
reste une 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)
}
Vous devez faire une assertion de type pour convertir votre interface {} en valeur int.
iAreaId := val.(int)
iAreaId, ok := val.(int)
Plus d'informations sont disponibles .
J'ai écrit une bibliothèque qui peut aider avec les conversions de types 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]
La façon la plus simple je l'ai fait. Pas le meilleur moyen mais le plus simple, je sais comment.
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
}