go语言 json解析求帮助

Loveyou
  • 37

json:

{
    "success": true,
    "message": "操作成功!",
    "code": 200,
    "result": [104887127, "xxxxx","xxxxx"],
    "timestamp": 1561395039616
}

有什么办法将该json解析到struct里面
其他的还好 但是 result 这个字段会有问题 拿不到对应的数据 而且第一个值还会被转为float64

目前的办法是 定义结构体 result 为 interface{}

    result = json.Unmarshal(jsonStr, &w)
    str := result.Result.([]interface{})
    str1 := str[0].(float64)
    newNum := big.NewRat(1, 1)
    newNum.SetFloat64(str1)

但是这样好繁琐啊 如果拿第二个值的时候要

result.Result.([]interface{})[1].(string)

如果拿第三个的时候要

result.Result.([]interface{})[2].(string)

有没有什么好的办法?

回复
阅读 1k
4 个回答

如果result里面是不同数据类型,且字段数不固定,只能用interface类型。

  1. 关于浮点数的问题,可以使用UseNumber方法
  2. 由于数组内部是整数和字符串,只能使用[]interface{} 类型,所以需要做一次转换。

例子如下:

    jsonStr := `[104887127, "xxxxx","xxxxx"]`
    data := []interface{}{}
    decoder := json.NewDecoder(strings.NewReader(jsonStr))
    decoder.UseNumber()
    decoder.Decode(&data)
    val1, _ := data[0].(json.Number).Int64()
    val2, val3 := data[1].(string), data[2].(string)
    fmt.Println(val1, val2, val3)
package main

import (
    "encoding/json"
    "fmt"
    "strconv"
)

type Number struct {
    s string
    i int
}

func (n *Number) IsString() bool {
    return n.s != ""
}

func (n *Number) String() string {
    return n.s
}

func (n *Number) Int() int {
    return n.i
}

func (n *Number) MarshalJSON() ([]byte, error) {
    if n.IsString() {
        return json.Marshal(n.String())
    }

    return json.Marshal(n.Int())
}

func (n *Number) UnmarshalJSON(data []byte) error {
    if data[0] == '"' && data[len(data)-1] == '"' {
        n.s = string(data[1 : len(data)-1])
        return nil
    }

    i, err := strconv.Atoi(string(data))
    if err != nil {
        return err
    }

    n.i = i
    return nil
}

type Data struct {
    Result []Number `json:"result"`
}

func main() {
    s := `{
    "success": true,
    "message": "操作成功!",
    "code": 200,
    "result": [104887127, "xxxxx","xxxxx", "0"],
    "timestamp": 1561395039616
}`

    data := &Data{}
    err := json.Unmarshal([]byte(s), data)
    if err != nil {
        panic(err)
    }

    fmt.Println(*data)

    body, err := json.Marshal(data)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))

}

代码输出:

{[{ 104887127} {xxxxx 0} {xxxxx 0} {0 0}]}
{"result":[104887127,"xxxxx","xxxxx","0"]}

Number 类型你可以增加任意方法,实现自己的需求,也可以把所有的数据都转成字符串方便访问

对于第三方的复杂JSON推荐使用https://github.com/tidwall/gjson,官方的方式过于啰嗦

package main

import (
    "fmt"
    "github.com/tidwall/gjson"
)

const jsonstr = `{
    "success": true,
    "message": "操作成功!",
    "code": 200,
    "result": [104887127, "xxxxx","xxxxx"],
    "timestamp": 1561395039616
}`


func main() {
    jval := gjson.Parse(jsonstr)
    fmt.Println(jval.Get("result.0").Int())
    fmt.Println(jval.Get("result.0").Type)
    fmt.Println(jval.Get("result.1").String())
    fmt.Println(jval.Get("result.1").Type)
    fmt.Println(jval.Get("result.2").String())
    fmt.Println(jval.Get("result.2").Type)
}   

输出结果:
104887127
Number
xxxxx
String
xxxxx
String

宣传栏