Like encoding/json
but stores graphs instead of trees.
Grison solves the following problems:
- Loops in the graph.
- Encoding and decoding of interface types.
Given that there's no obvious "starting point" in a graph and, in fact, there may not be a single node from which all the other nodes are reachable, grison requires that you create a "master" structure, i.e. a structure with pointers to all the nodes:
type Master struct{
Foo []*Foo
Bar []*Bar
}
You can then marshal/unmarshal this master structure as needed:
var m1 Master
...
b, err := grison.Marshal(&m1)
...
var m2 Master
err = grison.Unmarshal(b, &m2)
Struct tags work very much the same as with encoding/json
:
type Person struct {
Age int `grison:"age,omitempty"`
}
To get indented output, use Prefix
and Indent
options.
b, err := MarshalWithOpts(m, MarshalOpts{
Prefix: "> ",
Indent: " ",
})
Node IDs in the JSON file are automatically generated (#1, #2 etc.) However, if GetIDs
option is set, GetID
function will be called on each node and the result will be used as the ID. If a node doesn't implement GetID
function, marshaling will fail with an appropriate error.
b, err := MarshalWithOpts(m, MarshalOpts{
GetIDs: true,
})
At the moment there are no unmarshal options.
type Parent struct {
Name string
Sex string
Spouse *Parent
Children []*Child
}
type Child struct {
Name string
Age int
Father *Parent
Mother *Parent
}
type Master struct {
Parents []*Parent
Children []*Child
}
The data structures above can produce, for example, the following JSON:
{
"Children": {
"#3": {
"Age": 10,
"Father": {"$ref": "Parents:#2"},
"Mother": {"$ref": "Parents:#1"},
"Name": "Carol"
},
"#4": {
"Age": 8,
"Father": {"$ref": "Parents:#2"},
"Mother": {"$ref": "Parents:#1"},
"Name": "Dan"
}
},
"Parents": {
"#1": {
"Children": [
{"$ref": "Children:#3"},
{"$ref": "Children:#4"}
],
"Name": "Alice",
"Sex": "Female",
"Spouse": {"$ref": "Parents:#2"}
},
"#2": {
"Children": [
{"$ref": "Children:#3"},
{"$ref": "Children:#4"}
],
"Name": "Bob",
"Sex": "Male",
"Spouse": {"$ref": "Parents:#1"}
}
}
}