[Golang] JSON Unmarshal When Field Name is Determined at Runtime


Today I got a problem about unmarshalling JSON data. One of the field names in the JSON data can only be known at runtime. The JSON data looks like:

{
  "reels": {
    "highlight:1234567890": {
      ...
    }
  }
}

The field name highlight:1234567890 is the id of the query, and is known only at runtime. But to unmarshal JSON using json.Unmarshal in Go standard encoding/json package, you have to fill the JSON tag or name in the struct at compile-time. It seems impossible to decode the JSON data in this case, so I tried to search for the answers [1]. And the answer of the question [2] gives me the direction of how to unmarshal JSON in such cases.

The trick is replace runtime field name with fixed string!

The field name given at runtime is very unique, so it is very easy to replace the field name with another fixed string using strings.Replace in Go standard strings package.

Im my case, the field name highlight:1234567890 is stored in the variable id, and we can replace it with another fixed string reels_media as follows:

strings.Replace(jsonData, id, "reels_media", 1)

Now in our struct used to unmarshal JSON, we can declare as follows:

type highlightMedia struct {
      Reels struct {
              ReelsMedia struct{
                      ...
              } `json:"reels_media"`
      } `json:"reels"`
}

Now we can use json.Unmarshal as usual without any problem!

The other possible way to solve this problem is to retag at runtime, but it looks not simple, so I gave up. There is a third-party package retag which helps you do this, but I like to use only Go standard library if possible, so I did not give it a try.


Tested on: Ubuntu Linux 18.04, Go 1.10.2.

References:

[1]
[2]go - JSON Unmarshal when structure is determined at runtime - Stack Overflow
[3]go - Override Golang JSON tag values at runtime - Stack Overflow
[4]change code to adapt to change of the format of reels_media story hig… · siongui/instago@6bfcfff · GitHub
[5]Noob question regarding runes : golang