【问题标题】:golang convert json having array list to struct in glolanggolang将具有数组列表的json转换为golang中的结构
【发布时间】:2016-07-26 11:14:19
【问题描述】:

我是golang新手,我需要从下面的json字符串中获取数据。

{"data" : ["2016-06-21","2016-06-22","2016-06-25"], "sid" : "ab", "did" : "123"}

现在我尝试了一个类似的结构

type IntervalData struct {
    Data json.RawMessage `json:"data"`
    Did  string `json:"did"`
    Sid  string `json:"sid"`
}

type IntervalDataList []string

和像

这样的 json 解组代码
    r := IntervalData{}
    json.Unmarshal([]byte(json), &r)
    log.Printf("Raw  Body: %s", r)

    log.Printf("Raw Date Json: %s", r.Data)

    blist := IntervalDataList{}
    json.Unmarshal([]byte(r.Data), &blist)
    log.Printf("Date List : %s", blist)

此代码只能从 json 字符串获取 sid,而不是显示为空地图的数据。
从上面的json获取数据的方法是什么?

更新:问题已解决。我检查了我的输入 json 格式为{"data":"[\"dsadsdsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\n\"sdsdadsddad\"]","did":"654646456","sid":"88683627434"},这不是必需的格式。然后我检查了客户端脚本并根据在线资源进行了更改。 How to JSONize a uint8 slice in Go?

type RequestData struct {
    Data JSONableSlice `json:"data"`
    Did  string `json:"did"`
    Sid  string `json:"sid"`
}
type JSONableSlice []uint8

func (u JSONableSlice) MarshalJSON() ([]byte, error) {
    var result string
    if u == nil {
        result = "null"
    } else {
        result = strings.Join(strings.Fields(fmt.Sprintf("%d", u)), ",")
    }
    return []byte(result), nil
}

func ApiRequest(w http.ResponseWriter, r *http.Request) {
    sid := r.Header.Get("sid")
    deviceID := r.Header.Get("deviceId")

    body, err := ioutil.ReadAll(r.Body)
    failOnError(err, "Issue faced during reading post contents")
    data := RequestData{
        Data: body,
        Sid:  sid,
        Did:  dID,
    }

    bdata, err := json.Marshal(data)

    // Some Rabbit MQ Connection code

    // Rabbit MQ publish code
    err = ch.Publish(
        "",     // exchange
        q.Name, // routing key
        false,  // mandatory
        false,  // immediate
        amqp.Publishing{
            DeliveryMode: amqp.Persistent,
            ContentType:  "text/plain",
            Body:         bdata,
    })
}

现在不需要对消费者代码进行太多更改

    type IntervalData struct {
        //Data json.RawMessage `json:"data"`
        Data []byte `json:"data"`
        Did  string `json:"did"`
        Sid  string `json:"sid"`
    }
    r := IntervalData{}
    json.Unmarshal([]byte(json), &r)
    log.Printf("Raw  Body: %s", r)

    log.Printf("Raw Date Json: %s", r.Data)

    blist := IntervalDataList{}
    json.Unmarshal(r.Data, &blist)
    log.Printf("Date List : %s", blist)

【问题讨论】:

标签: json go json-deserialization


【解决方案1】:

在您的示例代码中,您指的是r.data,这是一个未导出字段!但是您的类型 IntervalData 有一个 exported IntervalData.Data 字段!这是不一致的。

所以很可能您的IntervalData 包含一个未导出 data 字段,json 包会忽略该字段,只有导出的字段被编组/解组。

只需更改要导出的IntervalData.data 字段:IntervalData.Data

查看这个工作示例:

j := `{"data" : ["2016-06-21","2016-06-22","2016-06-25"], "sid" : "ab", "did" : "123"}`
r := IntervalData{}
json.Unmarshal([]byte(j), &r)
log.Printf("Raw  Body: %s", r)

log.Printf("Raw Data Json: %s", r.Data)

blist := IntervalDataList{}
json.Unmarshal([]byte(r.Data), &blist)
log.Printf("Data List : %s", blist)

输出(在 Go Playground 上试试):

2009/11/10 23:00:00 Raw  Body: {["2016-06-21","2016-06-22","2016-06-25"] 123 ab}
2009/11/10 23:00:00 Raw Data Json: ["2016-06-21","2016-06-22","2016-06-25"]
2009/11/10 23:00:00 Data List : [2016-06-21 2016-06-22 2016-06-25]

还请注意,json.RawMessage 字段和第二次解组是不必要的,您可以将 Data 定义为 IntervalDataList 类型,并且它与单个解组一起工作:

Data IntervalDataList `json:"data"`

以及解组:

j := `{"data" : ["2016-06-21","2016-06-22","2016-06-25"], "sid" : "ab", "did" : "123"}`
r := IntervalData{}
json.Unmarshal([]byte(j), &r)
log.Printf("Raw Data Json: %s", r.Data)

输出(在 Go Playground 上试试这个):

2009/11/10 23:00:00 Raw Data Json: [2016-06-21 2016-06-22 2016-06-25]

【讨论】:

  • 哦,那是输入错误,我的代码只有数据变量而不是数据,但有趣的是代码在你给出的链接中工作。经过更多检查,我发现我的json变量不是字符串类型而是[]uint8类型,(它来自消息消费者响应)。
  • @kuldeep.kamboj []uint8[]byte 相同,json.RawMessage 是这样定义的:type RawMessage []byte
【解决方案2】:

下面的代码(或https://play.golang.org/p/kQRE7xYjrz)解析 JSON 字符串并提取/打印数据字段:

package main

import (
    "encoding/json"
    "fmt"
)

var data = []byte(`{"data" : ["2016-06-21","2016-06-22","2016-06-25"], "sid" : "ab", "did" : "123"}`)

type IntervalDataList []string

type IntervalData struct {
    Data IntervalDataList `json:"data"`
    Did  string           `json:"did"`
    Sid  string           `json:"sid"`
}

func main() {
    r := &IntervalData{}
    err := json.Unmarshal(data, r)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Data: %#v\n", r.Data)
}

输出:

Data: main.IntervalDataList{"2016-06-21", "2016-06-22", "2016-06-25"}

【讨论】:

  • 正如 icza 所指出的,初始代码也可以工作,但主要问题是实际的 json 与预期的 json 不同,后者在数据值周围添加了双引号(以及内部的转义引号)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-15
  • 2016-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多