简体   繁体   中英

Extract nested JSON as string

I have a JSON object which I am successfully able to convert to a Go struct. However, I have a requirement where I need to parse the nested object in that JSON as a string and I am unable to do it.

Here is the code that works.

The Simple JSON that WORKS

{
    "timestamp": "1232159332",
    "duration": 0.5,
}

It converts to the following struct

type Beat struct {
    Timestamp   string      `json:"timestamp"`
    Duration    float32     `json:"duration"`
}

func AddBeat(w http.ResponseWriter,  r *http.Request) {
    
    // Step 1 Get JSON parameters:
    b := Beat {}

    decoder := json.NewDecoder(r.Body)
    err := decoder.Decode(&b)
    checkErr(err)

    fmt.Println("Beat: ", b)
}

In the following JSON the nested data object is populated dynamically and its structure can vary. That's why I need to extract it as string and store it in the Database, but Go won't extract it as a string. This Doesn't Work

{
    "timestamp": "1232159332",
    "duration": 0.5,
    "data": {
       "key1": "val1",
       "key2": "val2"
    } 
}

Go Code (Doesn't Work)

type Beat struct {
    Timestamp   string      `json:"timestamp"`
    Duration    float32     `json:"duration"`
    Data        string      `json:"data"`
}

func AddBeat(w http.ResponseWriter,  r *http.Request) {
    
    // Step 1 Get JSON parameters:
    b := Beat {}

    decoder := json.NewDecoder(r.Body)
    err := decoder.Decode(&b)
    checkErr(err)

    fmt.Println("Beat: ", b)
}

This is the error I get

2020/11/25 10:45:24 http: panic serving [::1]:50082: json: cannot unmarshal object into Go struct field Beat.data of type string

Now, the question is how can I extract and decode a nested object in this case data as a string in Go?

You probably need to use json.RawMessage :

type Beat struct {
    Timestamp   string      `json:"timestamp"`
    Duration    float32     `json:"duration"`
    Data        json.RawMessage      `json:"data"`
}

data := []byte(`{
    "timestamp": "1232159332",
    "duration": 0.5,
    "data": {
       "key1": "val1",
       "key2": "val2"
    } 
}`)
b := Beat{}
err := json.Unmarshal(data, &b)
if err != nil {
    panic(err)
}
fmt.Println(string(b.Data))

https://play.golang.org/p/tHe4kBMSEEJ

Or implementing the Unmarshaller interface:

https://play.golang.org/p/p50GW57yH_U

type Beat struct {
    Timestamp   string      `json:"timestamp"`
    Duration    float32     `json:"duration"`
    Data        string      `json:"data"`
}

func (b *Beat) UnmarshalJSON(data []byte) error {
    type beat struct {
        Timestamp   string          `json:"timestamp"`
        Duration    float32         `json:"duration"`
        Data        json.RawMessage `json:"data"`
    }
    bb := &beat{}
    err := json.Unmarshal(data, bb)
    if err != nil {
        return err
    }
    b.Timestamp = bb.Timestamp
    b.Duration = bb.Duration
    b.Data = string(bb.Data)
    return nil
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM