-3

I am new to Go and stuck at unmarshelling json data. Facing trouble while unmarshelling JSON to struct for the response json that is getting returned as response.

The key for the couple of inner variables are anonymous. Thus unmarshelling them gives no data.

Json response is as below

{
  "data": [
    {
      "Name": "Dummy Value",
      "configEvents": {
        "5f94f412-532a-41a8-821e-6326dd72556b": {
          "eventId": "dummy",
          "start": "dummy",
          "end": "dummy",
          "details": {
            "providerCallSign": "dummy",
            "callSign": "dummy"
          }
        }
      },
      "policyEvents": {
        "930195be-f409-421c-abe2-a39d2450d669": {
          "details": {
            "daiMobileFlag": false
          }
        }
      }
    }
  ]
}

My struct is as follow

type Response struct {
    Data []struct {
        Name         string `json:"Name"`
        ConfigEvents struct {
            FiveF94F412532A41A8821E6326Dd72556B struct {
                EventID string `json:"eventId"`
                Start   string `json:"start"`
                End     string `json:"end"`
                Details struct {
                    ProviderCallSign string `json:"providerCallSign"`
                    CallSign         string `json:"callSign"`
                } `json:"details"`
            } `json:"5f94f412-532a-41a8-821e-6326dd72556b"`
        } `json:"configEvents"`
        PolicyEvents struct {
            Nine30195BeF409421CAbe2A39D2450D669 struct {
                Details struct {
                    DaiMobileFlag bool `json:"daiMobileFlag"`
                } `json:"details"`
            } `json:"930195be-f409-421c-abe2-a39d2450d669"`
        } `json:"policyEvents"`
    } `json:"data"`
}

As the key is dynamic in the response, unmarshelling does not capture that particular object. Is there any way to handle this scenario in goLang.

  • 1
    What do you mean that the "keys are anonymous"? Keys always have a value. If the keys are not static you use a `map`. – JimB Dec 18 '20 at 16:39
  • 2
    Does [How to parse/deserialize dynamic JSON](https://stackoverflow.com/a/29347148/5728991) answer your question? – Charlie Tumahai Dec 18 '20 at 16:41
  • the example JSON you give is invalid – Vorsprung Dec 18 '20 at 16:42
  • @JimB key name i.e. uuid in this case (the object inside configEvents), this would be dynamic for every response. Is it clear now? – Tejas Ghonge Dec 18 '20 at 17:36
  • @Vorsprung Edited just now, there were few * characters present. Now its good. – Tejas Ghonge Dec 18 '20 at 17:37
  • @CeriseLimón That would be too complicated to parse the map again, instead if we could marshal it, then it would be better for further operations. – Tejas Ghonge Dec 18 '20 at 17:45
  • 3
    @TejasGhonge: again, if the keys are not statically known ahead of time, you need to use a map. You cannot change struct fields dynamically at runtime. – JimB Dec 18 '20 at 17:49
  • 2
    Cu@TejasGhonge you don’t need to parse the map again. Use a map type instead of a struct type where the keys are dynamic. – Charlie Tumahai Dec 18 '20 at 17:56
  • @CeriseLimón Can you please explain that with couple of lines of code snippet, I am not getting the exact point. – Tejas Ghonge Dec 18 '20 at 18:07
  • 1
    Change the type of the ConfigEvents field to a map: `ConfigEvents map[string]struct { EventID ...` See [1](https://stackoverflow.com/a/50749936/5728991), [2](https://stackoverflow.com/a/40509559/5728991). – Charlie Tumahai Dec 18 '20 at 18:13
  • 2
    Note this will be easier to write an maintain if you use named types instead of anonymous structs. That way it's simply something like `map[string]configEvent`. – JimB Dec 18 '20 at 18:39
  • @CeriseLimón Perfect! Thats the answer I was looking for.. Thanks a lot – Tejas Ghonge Dec 18 '20 at 18:45
  • @JimB Yep, this solved my issue..Thanks mate – Tejas Ghonge Dec 18 '20 at 18:46

1 Answers1

1

I fixed the json to something similar that is valid like this

    {
  "data": [
    {
      "Name": "Dummy Value",
      "configEvents": {
        "5f94f412-532a-41a8-821e-6326dd72556b": {
          "eventId": "dummy",
          "start": "dummy",
          "end": "dummy",
          "details": {
            "providerCallSign": "dummy",
            "callSign": "dummy"
          }
        }
      },
      "policyEvents": {
        "930195be-f409-421c-abe2-a39d2450d669": {
          "details": {
            "daiMobileFlag": false
          }
        }
      }
    }
  ]
}

Then this code works to ingest it

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
)

type insideConfigEvents struct {
    EventID string `json:"eventId"`
    Start   string `json:"start"`
    End     string `json:"end"`
    Details struct {
        ProviderCallSign string `json:"providerCallSign"`
        CallSign         string `json:"callSign"`
    } `json:"details"`
}

type insidePolicyEvents struct {
    Details struct {
        DaiMobileFlag bool `json:"daiMobileFlag"`
    } `json:"details"`
}

type Input struct {
    Data []struct {
        Name         string                        `json:"Name"`
        ConfigEvents map[string]insideConfigEvents `json:"configEvents"`
        PolicyEvents map[string]insidePolicyEvents `json:"policyEvents"`
    } `json:"data"`
}

func main() {
    var dat Input
    b, err := ioutil.ReadFile("inv.json") // just pass the file name
    if err != nil {
        fmt.Print(err)
    }
    if err := json.Unmarshal(b, &dat); err != nil {
        panic(err)
    }
    fmt.Println(dat.Data[0].ConfigEvents)
}
Vorsprung
  • 32,923
  • 5
  • 39
  • 63