简体   繁体   中英

Extracting Elements from JSON

I have a function that returns JSON, and the return type is this:

map[string]interface{}

In my particular case, I know that the returned JSON looks like this:

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

I want to get the value of "stringInArray" and also "anotherString". I've searched for solutions for example from Go by Example and blog.golang.org but I've not been successful.

For example, given that res is the json returned from the function call, I tried this (from the go blog):

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")
    }
}

(I know the above would not do exactly what I want but it is a start.) But when code execution hits b := []byte( res ) , I get this error:

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

What is the most efficient method / best practice for obtaining the values? I'm open to any solution, not necessarily the approach above.

@sydnash Here is the code I promised in my response to your comment:

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}}}

I think you should use b := []byte(res) instead b :=[]byte[ res ] and res should be a json string or []byte. res is not a legal json format.

this information maybe help you: To unmarshal JSON into an interface value, Unmarshal stores one of these in the interface value:

bool, for JSON booleans

float64, for JSON numbers

string, for JSON strings

[]interface{}, for JSON arrays

map[string]interface{}, for JSON objects

nil for JSON null

you can see there is no int but float64 for JSON numbers.

There is an example of how to unmarshal json in the docs on golang packages encoding/json . Essentially your problem is that the un-marshal expects to be putting the json into type . So your code must declare a type that represents the json you are converting from.

Example of the json and the declared type from the linked example:

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

Once you define the type it should all fall into place.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM