Skip to content

Instantly share code, notes, and snippets.

@ryanmoran
Created May 3, 2019 21:05
Show Gist options
  • Save ryanmoran/e5da2c5a601e585aa3b703acaa4ccd60 to your computer and use it in GitHub Desktop.
Save ryanmoran/e5da2c5a601e585aa3b703acaa4ccd60 to your computer and use it in GitHub Desktop.
JSON Pointer Exploration
package main
import (
"encoding/json"
"fmt"
"os"
"strings"
"github.com/qri-io/jsonpointer"
)
func main() {
file, err := os.Open("schema.json")
if err != nil {
panic(err)
}
var schema map[string]interface{}
err = json.NewDecoder(file).Decode(&schema)
if err != nil {
panic(err)
}
resolved, err := walk(schema, schema, 0)
if err != nil {
panic(err)
}
encoder := json.NewEncoder(os.Stdout)
encoder.SetIndent("", " ")
encoder.Encode(resolved)
}
func walk(root map[string]interface{}, node interface{}, depth int) (interface{}, error) {
switch value := node.(type) {
case map[string]interface{}:
resolvedValue := map[string]interface{}{}
for k, v := range value {
if k == "$ref" {
fmt.Printf("%s%s -> hit: %s\n", strings.Repeat(" ", depth), k, v)
result, err := find(root, v.(string))
if err != nil {
return nil, err
}
return result, nil
} else {
fmt.Printf("%s%s -> miss\n", strings.Repeat(" ", depth), k)
result, err := walk(root, v, depth+1)
if err != nil {
return nil, err
}
resolvedValue[k] = result
}
}
node = resolvedValue
case []interface{}:
fmt.Printf("%s[\n", strings.Repeat(" ", depth))
resolvedValue := []interface{}{}
for _, v := range value {
result, err := walk(root, v, depth+1)
if err != nil {
return nil, err
}
resolvedValue = append(resolvedValue, result)
}
fmt.Printf("%s]\n", strings.Repeat(" ", depth))
node = resolvedValue
}
return node, nil
}
func find(root map[string]interface{}, path string) (interface{}, error) {
ptr, err := jsonpointer.Parse(path)
if err != nil {
return nil, err
}
subgraph, err := ptr.Eval(root)
if err != nil {
return nil, err
}
return subgraph, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment