2016-12-01 2 views
0

j'ai une fonction qui retourne JSON, et le type de retour est ceci:éléments DEGAGER JSON

map[string]interface{} 

Dans mon cas, je sais que le JSON retourné ressemble à ceci:

{ 
    "someNumber": 1, 
    "someString": "ee", 
    "someArray": [ 
    "stringInArray", 
    { 
     "anotherNumber": 100, 
     "anotherString": "asdf", 
     "yetAnotherString": "qwer" 
    } 
    ] 
} 

Je veux obtenir la valeur de "stringInArray" et aussi "anotherString". J'ai cherché des solutions par exemple de Go by Example et blog.golang.org mais je n'ai pas réussi.

Par exemple, étant donné que res est le JSON retour de l'appel de fonction, j'ai essayé ceci (du blog go):

var f interface{} 
b := []byte(`res`) 
err2 := json.Unmarshal(b, &f) 
if err2!=nil{ 
    log.Fatalf("Err unmarshalling: %v", err2) 
} 

m := f.(map[string]interface{}) 

for k, v := range m { 
    switch vv := v.(type) { 
    case string: 
     fmt.Println(k, "is string", vv) 
    case int: 
     fmt.Println(k, "is int", vv) 
    case []interface{}: 
     fmt.Println(k, "is an array:") 
     for i, u := range vv { 
      fmt.Println(i, u) 
     } 
    default: 
     fmt.Println(k, "is of a type I don't know how to handle") 
    } 
} 

(Je sais que le ferait pas au-dessus exactement ce que je veux mais il est un bon début) mais quand l'exécution de code frappe b:. = [] octet (res), je reçois cette erreur:

Err unmarshalling: invalid character 'r' looking for beginning of value 

Quelle est la plus efficace méthode/meilleure pratique pour obtenir les valeurs? Je suis ouvert à toute solution, pas nécessairement l'approche ci-dessus.

@sydnash Voici le code que je promis dans ma réponse à votre commentaire:

type LoginResponse2 struct { 

    id float64 
    jsonrpc string 
    result struct { 
     token string 
     details struct { 
      a float64 
      b string 
      c float64 
     } 
    } 
} 

var resStruct2 LoginResponse2 
// Convert result to json 
b, _ :=json.Marshal(res) 
fmt.Println(string(b)) 
// results of Println: 
{"id":1,"jsonrpc":"2.0","result":[ "myToken",{"a":someNumber,"b":"some string","c":someOtherNumber} ] } 


// Unmarshall json into struct 
err2 := json.Unmarshal(b, &resStruct2) 
if err2 != nil { 
    log.Fatalf("Error unmarshalling json: %v", err) 
} 

fmt.Println("Here is json unmarshalled into a struct") 
fmt.Println(resStruct2) 
// results of Println 
{0 { {0 0}}} 
+2

La chaîne '" res "' n'est pas valide json, donc vous ne pouvez pas démaraître de celle-ci. – JimB

Répondre

1

Je pense que vous devriez utiliser b: = [] byte (res) au lieu de b: = [] byte [res] et res devrait être une chaîne json ou [] octet. res n'est pas un format JSON légal.

cette information peut-être vous aider: à unmarshal JSON en une valeur d'interface, unmarshal stocke un de ceux-ci dans la valeur de l'interface:

bool, pour JSON booléens

float64, pour les numéros JSON

chaîne, pour les chaînes JSON

[] l'interface {}, pour les tableaux JSON

carte [chaîne] l'interface {}, pour les objets JSON

nul pour JSON null

vous pouvez voir qu'il n'y a pas int, mais float64 pour les numéros JSON.

+0

Merci, sydnash. Le premier problème que j'ai à résoudre est le suivant: ** res ** est ** map [string] interface {} ** et pas valide json. Comment convertir en json? –

+0

Grâce à un processus d'itération très verbeux sur l'objet 'res', j'ai pu extraire des valeurs et peupler une structure (ce que je veux faire en fonction de la réponse de @ miltonb à propos de jmarshalling json dans la structure), mais j'ai que je reproduis juste ce que fait la fonction 'json.Unmarshall'. Donc, je serais toujours intéressé de savoir s'il existe un moyen assez simple de convertir l'interface 'map [string] interface {}' en json. Merci. –

+0

vous voulez dire que vous voulez convertir la carte en json? Si tout type de valeur d'élément est de type intégré, cet exemple peut vous aider. https://play.golang.org/p/rpy1Txz6wK – sydnash

1

Il est un exemple de la façon de désorganiser JSON dans la documentation sur les paquets de golang encoding/json. Essentiellement, votre problème est que le un-marshal s'attend à mettre le json dans type. Donc, votre code doit déclarer un type qui représente le json à partir duquel vous convertissez.

Exemple de JSON et le type déclaré de l'exemple lié:

var jsonBlob = []byte(`[ 
    {"Name": "Platypus", "Order": "Monotremata"}, 
    {"Name": "Quoll", "Order": "Dasyuromorphia"} 
]`) 
type Animal struct { 
    Name string 
    Order string 
} 

Une fois que vous définissez le type il se doit tout tomber en place.

+1

Merci, miltonb. Si je vous comprends bien, je dois créer une structure qui représente le json –

+0

Oui c'est correct. – miltonb

+1

Vous pouvez également utiliser la bibliothèque [mapstructure] (https://github.com/mitchellh/mapstructure) si le schéma de votre entrée JSON change de façon imprévisible. –