-
Notifications
You must be signed in to change notification settings - Fork 13
/
marshal.go
74 lines (61 loc) · 2.48 KB
/
marshal.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package aini
import (
"encoding/json"
"github.com/samber/lo"
"golang.org/x/exp/maps"
)
type alwaysNil interface{} // to hold place for Group and Host references; must be nil in serialized form
func (group *Group) MarshalJSON() ([]byte, error) {
type groupWithoutCustomMarshal Group
return json.Marshal(&struct {
groupWithoutCustomMarshal
Hosts map[string]alwaysNil
Children map[string]alwaysNil
Parents map[string]alwaysNil
DirectParents map[string]alwaysNil
}{
groupWithoutCustomMarshal: groupWithoutCustomMarshal(*group),
Hosts: makeNilValueMap(group.Hosts),
Children: makeNilValueMap(group.Children),
Parents: makeNilValueMap(group.Parents),
DirectParents: makeNilValueMap(group.DirectParents),
})
}
func (host *Host) MarshalJSON() ([]byte, error) {
type hostWithoutCustomMarshal Host
return json.Marshal(&struct {
hostWithoutCustomMarshal
Groups map[string]alwaysNil
DirectGroups map[string]alwaysNil
}{
hostWithoutCustomMarshal: hostWithoutCustomMarshal(*host),
Groups: makeNilValueMap(host.Groups),
DirectGroups: makeNilValueMap(host.DirectGroups),
})
}
func makeNilValueMap[K comparable, V any](m map[K]*V) map[K]alwaysNil {
return lo.MapValues(m, func(_ *V, _ K) alwaysNil { return nil })
}
func (inventory *InventoryData) UnmarshalJSON(data []byte) error {
type inventoryWithoutCustomUnmarshal InventoryData
var rawInventory inventoryWithoutCustomUnmarshal
if err := json.Unmarshal(data, &rawInventory); err != nil {
return err
}
// rawInventory's Groups and Hosts should now contain all properties,
// except child group maps and host maps are filled with original keys and null values
// reassign child groups and hosts to reference rawInventory.Hosts and .Groups
for _, group := range rawInventory.Groups {
group.Hosts = lo.PickByKeys(rawInventory.Hosts, maps.Keys(group.Hosts))
group.Children = lo.PickByKeys(rawInventory.Groups, maps.Keys(group.Children))
group.Parents = lo.PickByKeys(rawInventory.Groups, maps.Keys(group.Parents))
group.DirectParents = lo.PickByKeys(rawInventory.Groups, maps.Keys(group.DirectParents))
}
for _, host := range rawInventory.Hosts {
host.Groups = lo.PickByKeys(rawInventory.Groups, maps.Keys(host.Groups))
host.DirectGroups = lo.PickByKeys(rawInventory.Groups, maps.Keys(host.DirectGroups))
}
inventory.Groups = rawInventory.Groups
inventory.Hosts = rawInventory.Hosts
return nil
}