douzhan5058
douzhan5058
2016-12-01 21:24

从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}}}
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

2条回答

  • dongya0914 dongya0914 5年前

    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.

    点赞 评论 复制链接分享
  • dongshou6788 dongshou6788 5年前

    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.

    点赞 评论 复制链接分享

相关推荐