drb56625
2016-10-07 09:54
浏览 99

Golang Unmarshal JSON

My input JSON, has a list of different elements.
I have problems with the number of the first element of response.

Simplified example:

package main

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

var j = ` {
  "response": [
    777, // problem here !!!
    {
      "id": 888,
      "from_id": 999,
      "to_id": 888,
      "text": "hello..."
    },
        {
      "id": 999,
      "from_id": 888,
      "to_id": 999,
            "text": "goodbye..."
    }
  ]
}`

type D struct {
    Id     int `json:"id"`
    FromId int `json:"from_id"`
    ToId   int `json:"to_id"`
    Text   string `json:"text"`
}

type R struct {
    Count    int
    Response []D `json:"response"`
}

func main() {
    var data = new(R)
    err := json.Unmarshal([]byte(j), &data)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(data.Response)
}

Error on output. I do not understand where the error. Help me please.


  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • duanhunlou7051 2016-10-07 10:50
    已采纳

    1- Here is the working code,try it on The Go Playground:

    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    func main() {
        var d *R
        err := json.Unmarshal([]byte(str), &d)
        if err != nil {
            panic(err)
        }
        var data R2
        data.Count = int(d.Response[0].(float64))
    
        for _, v := range d.Response[1:] {    
            bs, err := json.Marshal(v)
            if err != nil {
                panic(err)
            }
            var d1 *D
            err = json.Unmarshal(bs, &d1)
            if err != nil {
                panic(err)
            }
            data.Response = append(data.Response, *d1)
        }
        fmt.Println(data)    
    }
    
    type R struct {
        Response []interface{} `json:"response"`
    }
    
    var str = ` {
      "response": [
        777,  
        {
          "id": 888,
          "from_id": 999,
          "to_id": 888,
          "text": "hello"
        },
            {
          "id": 999,
          "from_id": 888,
          "to_id": 999,
                "text": "goodbye"
        }
      ]
    }`
    
    type D struct {
        Id     int    `json:"id"`
        FromId int    `json:"from_id"`
        ToId   int    `json:"to_id"`
        Text   string `json:"text"`
    }
    type R2 struct {
        Count    int
        Response []D
    }
    

    output:

    {777 [{888 999 888 hello} {999 888 999 goodbye}]}
    
    点赞 评论
  • dongwuxie7976 2016-10-07 10:20

    Your response json is invalid. You use array instead of structure with fields specified in type D.

    点赞 评论
  • dtkvlj5386 2016-10-10 22:34

    I have a different approach: https://play.golang.org/p/9Xnxk7tVxE

    All you have to do is implement the Unmarshaler interface and add the logic inside the method UnmarshalJSON. It's a similar solution to the other one, but it's more portable since you don't have to do that in the main or external method and it's little more robust :)

    package main
    
    import (
        "encoding/json"
        "fmt"
        "log"
    )
    
    var j = `{
      "response": [
        777,
        {
          "id": 888,
          "from_id": 999,
          "to_id": 888,
          "text": "hello..."
        },
        {
          "id": 999,
          "from_id": 888,
          "to_id": 999,
                "text": "goodbye..."
        }
      ]
    }`
    
    type D struct {
        Id     int    `json:"id"`
        FromId int    `json:"from_id"`
        ToId   int    `json:"to_id"`
        Text   string `json:"text"`
    }
    
    type R struct {
        Count    int
        Response []D
    }
    
    func (r *R) UnmarshalJSON(data []byte) error {
        var values struct {
            Resp []interface{} `json:"response"`
        }
    
        if err := json.Unmarshal(data, &values); err != nil {
            return err
        }
    
        if len(values.Resp) < 1 {
            return fmt.Errorf("empty response %v", values.Resp)
        }
    
        count, isNumber := values.Resp[0].(float64)
        if !isNumber {
            return fmt.Errorf("first element has to be a number, we got '%T'", values.Resp[0])
        }
        r.Count = int(count)
    
        for _, elem := range values.Resp[1:] {
            de, err := json.Marshal(elem)
            if err != nil {
                return err
            }
            var d D
            if err := json.Unmarshal(de, &d); err != nil {
                return err
            }
            r.Response = append(r.Response, d)
        }
        return nil
    }
    
    func main() {
        var data = new(R)
        if err := json.Unmarshal([]byte(j), &data); err != nil {
            log.Fatal(err)
        }
        fmt.Println(*data)
    }
    
    点赞 评论

相关推荐 更多相似问题