Dynamic Json Marshalling and Unmarshalling

type General struct {
Type string json:"type"
LookUp []interface json:"lookup"
}

type Human struct {
Name string json:"name"
Feature string json:"feature"
}

type Animal struct {
Name string json:"name"
Type string json:"type" Example int json:“example”`
}

str := { "type": "living", "lookup": [ { "name": "human", "feature": "think" }, { "name": "animal", "type": "carnivores", "example": "lion" }, { "name": "animal", "type": "herbivores", "example": "zebra" } ] }

Based on “name” field how can we perform dynamic json unmarshalling and marshalling ?

Option 1: Rethink your problem domain. Does the JSON data really have to be a mishmash of different data types? Can you untangle the data to separate Human from Animal in your JSON data? Can you produce JSON data that is predictable when reading?

Option 2: Rethink your data. Does the Human struct necessarily need to be different from the Animal struct? Can both consist of Feature, Type, and Example fields? In other words, can one single, unified struct do the trick?

Option 3: Find a suitable third-party JSON package that does the trick. (Search on godoc.org, pkg.go.dev, github.com…)

Option 4: Roll your own dynamic unmarshalling. Explaining this one I’ll leave to the experts of dynamic unmarshalling…

1 Like

This is an example of an actual scenario that is needed in my project. The fields here are arbitrary, trying to replicate the model I am using.

The actual problem is I need to form a mixed playlist of different types of screens such as commercial screen, statistic screen, etc.

The struct is as follows:

type PlayList struct {
ID string json:"id"

Screens []interface json:"screens"
}

type Commercials struct {
Brand string json:"brand"

}

type Stats struct {
Product string json:"product" Growth int json:“growth”`

}

The screen field in playlist can comprise of various numbers of Stats, Commercials,etc…

If I’m understanding your problem correctly, you have a container ‘PlayList’ which when returned contains a list of Screens which who’s fields are variable.
One thing you can do if you know what fields will be returned each time is to create a ‘Screen’ type and associate all the possible fields which can be contained in the ‘Screen’ type and then tag them with ‘omitempty’

type Screen struct {
Brand string json:"brand,omitempty"
Product string json:"product,omitempty"
XAxis int json:"x_axis,omitempty" Spend int json:“total_spend,omitempty”`
etc…
}

Your container struct would look like this.

type PlayList struct {
ID string json:"id"
Screens []Screen `json:“screens”
}

If you don’t know what possible fields which will be returned in the Screen type then it becomes a bit more complicated. Golang is a strongly typed language and as such handles predictable data fairly well but doesn’t do as well with data that is unpredictable or not strongly typed.

I recently had to write something which took data with no predictable fields and somehow still generate a struct and be able to unmarshal it. The only way I found to do this reliably was to do code generation. and deconstructing the JSON data, determining the data type, the field name and the value and creatin a struct.go file from that information.

I wrote a package to handle most of the heavy lifting for me. It’s not good. It could use a lot of fixing up. But I post it here in case it might be helpful to you.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.