0
votes

I am new to golang, I need to get data from following json string.

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

For now I tried a struct with similar

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

type IntervalDataList []string

and json unmarshall code like

    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)

This code only able to get sid and did from json string not data which shown as empty map.
What can be the way to get data from above json.

UPDATE : Issue resolved. I checked my input json comes in format of {"data":"[\"dsadsdsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\n\"sdsdadsddad\"]","did":"654646456","sid":"88683627434"} which is not required form. Then I checked client script and make changes according to online sources. 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,
    })
}

Not much changes required in consumer code now

    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)
2
Maybe I missed the point, but what speaks against having declared IntervalData.Data as []string? play.golang.org/p/ken-wOlYBf - Havelock

2 Answers

1
votes

In your example code you are referring to r.data which is an unexported field! But your type IntervalData has an exported IntervalData.Data field! This is inconsistent.

So most likely your IntervalData contains an unexported data field, which the json package ignores, only exported fields are marshaled / unmarshaled.

Simply change the IntervalData.data field to be exported: IntervalData.Data.

See this working example:

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)

Output (try it on the 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]

Also note that the json.RawMessage field and a second unmarshaling is unnecessary, you can define the Data to be of type IntervalDataList and it works with a single unmarshal:

Data IntervalDataList `json:"data"`

And unmarshaling:

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)

Output (try this on the Go Playground):

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

The code below (or in https://play.golang.org/p/kQRE7xYjrz) parses the JSON string and extracts/prints the Data field:

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

Output:

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