Skip to content

Instantly share code, notes, and snippets.

@wingeng
Created October 12, 2018 01:13
Show Gist options
  • Save wingeng/05f0ce041a980e946158515d06a99e18 to your computer and use it in GitHub Desktop.
Save wingeng/05f0ce041a980e946158515d06a99e18 to your computer and use it in GitHub Desktop.
Example of using gojay JSON decoder on Recursive structure
//
// An example of using gojay to decode a 'recursive' data-structure
// typical of hierarchal data used in a cli.
//
// Keywords: Decode JSON recursive
//
package main
import (
"testing"
"github.com/francoispqt/gojay"
)
type ItemArrayT []Item
type Item struct {
name string
help string
child ItemArrayT
}
//
// Interface for the array of Items, used to decode the array
//
func (item *ItemArrayT) UnmarshalJSONArray(dec *gojay.Decoder) error {
it := Item{}
if err := dec.Object(&it); err != nil {
return err
}
*item = append(*item, it)
return nil
}
//
// Interface for the decoding of the main object
//
func (item *Item) UnmarshalJSONObject(dec *gojay.Decoder, key string) error {
switch key {
case "name":
return dec.String(&(item.name))
case "help":
return dec.String(&(item.help))
case "child":
return dec.AddArray(&(item.child))
}
return nil
}
//
// Gotta tell gojay how many keys Item has
//
func (item *Item) NKeys() int {
return 3
}
//
// Helper function for testing. Errors reported here are not reported
// here, instead the go-test framework will report it at the
// caller site. Cool how this works. Note also how we use
// interface{} types to do generic equality testing, so you can pass
// in two strings, two floats, two integers
//
func test_eq(t *testing.T, s1, s2 interface{}) {
t.Helper()
if s1 != s2 {
t.Errorf("'%v' is not equaled to '%v'", s1, s2)
}
}
//
// Main test routine
//
func TestRecursive(t *testing.T) {
str := []byte(`
{
"name": "top",
"help": "Help for top level",
"child" : [ {
"name": "interfaces",
"help": "Show interface help file",
"child" : [{
"name": "unit",
"help": "Help for unit",
}, {
"name": "other",
"help": "Help for other"
}]
}]
}`)
top := &Item{}
err := gojay.UnmarshalJSONObject(str, top)
if err != nil {
t.Fatal(err)
}
test_eq(t, top.name, "top")
test_eq(t, len(top.child), 1)
test_eq(t, top.child[0].name, "interfaces")
test_eq(t, len(top.child[0].child), 2)
test_eq(t, top.child[0].child[0].name, "unit")
test_eq(t, top.child[0].child[0].help, "Help for unit")
test_eq(t, top.child[0].child[1].name, "other")
test_eq(t, top.child[0].child[1].help, "Help for other")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment