Skip to content

Instantly share code, notes, and snippets.

@EntityFX
Created January 20, 2023 10:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EntityFX/1beb70e8832e2638a0e857884246bc87 to your computer and use it in GitHub Desktop.
Save EntityFX/1beb70e8832e2638a0e857884246bc87 to your computer and use it in GitHub Desktop.
Marshal/Unmarshal json with inheritance
/*
Child1 =>
{
"a": "string",
"b": 7,
"type" : 0,
"field1" : "f1",
"field2" : [0, 1, "some", true],
...
}
For Child1: Meta map will contain missing fields (field1, fiel2, etc)
Child2 =>
{
"a": "string",
"b": 9,
"type" : 1,
"d": "SomeD"
}
*/
package main
import (
"encoding/json"
"fmt"
)
type ItemType int
const (
Child1Type ItemType = iota
Child2Type
)
type Base struct {
A string `json:"a"`
B int `json:"b"`
Type ItemType `json:"type"`
}
type Child1 struct {
*Base
C float64 `json:"c"`
Meta map[string]any
}
type Child2 struct {
*Base
D string `json:"d"`
}
func (p *Child1) MarshalJSON() ([]byte, error) {
m := map[string]any{
"a": p.Base.A,
"b": p.Base.B,
"type": p.Base.Type,
}
for key, value := range p.Meta {
m[key] = value
}
return json.Marshal(m)
}
func (ce *Base) UnmarshalJSON(b []byte) error {
var objMap map[string]any
// We'll store the error (if any) so we can return it if necessary
err := json.Unmarshal(b, &objMap)
if err != nil {
return err
}
if objMap["type"] == Child1Type {
return nil
}
return nil
}
func main() {
child1 := &Child1{
Base: &Base{
A: "String",
B: 7,
Type: Child1Type,
},
C: 1.23,
Meta: map[string]any{
"Field1": 24.7,
"FieldArr": []int{1, 2, 3},
},
}
child2 := &Child2{
Base: &Base{
A: "String",
B: 9,
Type: Child2Type,
},
D: "SomeD",
}
child1JsonBytes, _ := json.MarshalIndent(child1, "", " ")
child2JsonBytes, _ := json.Marshal(child2)
child1Json := string(child1JsonBytes)
child2Json := string(child2JsonBytes)
fmt.Printf("%v\n", child1Json)
fmt.Printf("%v\n", child2Json)
baseNew := &Base{}
json.Unmarshal([]byte(child1Json), baseNew)
fmt.Printf("%v\n", baseNew)
json.Unmarshal([]byte(child2Json), baseNew)
fmt.Printf("%v\n", baseNew)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment