0

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

2 Answers 2

1

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]
Sign up to request clarification or add additional context in comments.

2 Comments

Oh that is typing mistake, My code only have Data variable not data, But interestingly code working in link you given. After more checking, I found I json variable is not string type but []uint8 type, ( It comes from a message consumer response ) .
@kuldeep.kamboj []uint8 is the same as []byte, which is how json.RawMessage is defined: type RawMessage []byte
0

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

1 Comment

As icza points, initial code is also working, But main issue is actual json is different than expected json, which add double quotes around data value (and escape quotes inside too).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.