jsref

package module
v0.0.0-...-c0bcbb5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 28, 2021 License: MIT Imports: 8 Imported by: 17

README

go-jsref

Build Status

GoDoc

JSON Reference Implementation for Go

SYNOPSIS

package jsref_test

import (
  "encoding/json"
  "fmt"
  "log"

  jsref "github.com/lestrrat-go/jsref"
  "github.com/lestrrat-go/jsref/provider"
)

func Example() {
  var v interface{}
  src := []byte(`
{
  "foo": ["bar", {"$ref": "#/sub"}, {"$ref": "obj2#/sub"}],
  "sub": "baz"
}`)
  if err := json.Unmarshal(src, &v); err != nil {
    log.Printf("%s", err)
    return
  }

  // External reference
  mp := provider.NewMap()
  mp.Set("obj2", map[string]string{"sub": "quux"})

  res := jsref.New()
  res.AddProvider(mp) // Register the provider

  data := []struct {
    Ptr string
    Options []jsref.Option
  }{
    {
      Ptr: "#/foo/0", // "bar"
    },
    {
      Ptr: "#/foo/1", // "baz"
    },
    {
      Ptr: "#/foo/2", // "quux" (resolves via `mp`)
    },
    {
      Ptr: "#/foo",   // ["bar",{"$ref":"#/sub"},{"$ref":"obj2#/sub"}]
    },
    {
      Ptr: "#/foo",   // ["bar","baz","quux"]
      // experimental option to resolve all resulting values
      Options: []jsref.Option{ jsref.WithRecursiveResolution(true) },
    },
  }
  for _, set := range data {
    result, err := res.Resolve(v, set.Ptr, set.Options...)
    if err != nil { // failed to resolve
      fmt.Printf("err: %s\n", err)
      continue
    }
    b, _ := json.Marshal(result)
    fmt.Printf("%s -> %s\n", set.Ptr, string(b))
  }

  // OUTPUT:
  // #/foo/0 -> "bar"
  // #/foo/1 -> "baz"
  // #/foo/2 -> "quux"
  // #/foo -> ["bar",{"$ref":"#/sub"},{"$ref":"obj2#/sub"}]
  // #/foo -> ["bar","baz","quux"]
}

Providers

The Resolver object by default does not know how to resolve any reference: You must provide it one or more Providers to look for and resolve external references.

Currently available Providers are:

Name Description
provider.FS Resolve from local file system. References must start with a file:/// prefix
provider.Map Resolve from in memory map.
provider.HTTP Resolve by making HTTP requests. References must start with a http(s?):// prefix

References

Name Notes
go-jsval Validator generator
go-jshschema JSON Hyper Schema implementation
go-jsschema JSON Schema implementation
go-jspointer JSON Pointer implementations

Acknowledgements

  • Boris Burtin

Documentation

Overview

Example
package main

import (
	"encoding/json"
	"fmt"
	"log"

	jsref "github.com/lestrrat-go/jsref"
	"github.com/lestrrat-go/jsref/provider"
)

func main() {
	var v interface{}
	src := []byte(`
{
  "foo": ["bar", {"$ref": "#/sub"}, {"$ref": "obj2#/sub"}],
  "sub": "baz"
}`)
	if err := json.Unmarshal(src, &v); err != nil {
		log.Printf("%s", err)
		return
	}

	// External reference
	mp := provider.NewMap()
	_ = mp.Set("obj2", map[string]string{"sub": "quux"})

	res := jsref.New()
	_ = res.AddProvider(mp) // Register the provider

	data := []struct {
		Ptr     string
		Options []jsref.Option
	}{
		{
			Ptr: "#/foo/0", // "bar"
		},
		{
			Ptr: "#/foo/1", // "baz"
		},
		{
			Ptr: "#/foo/2", // "quux" (resolves via `mp`)
		},
		{
			Ptr: "#/foo", // ["bar",{"$ref":"#/sub"},{"$ref":"obj2#/sub"}]
		},
		{
			Ptr: "#/foo", // ["bar","baz","quux"]
			// experimental option to resolve all resulting values
			Options: []jsref.Option{jsref.WithRecursiveResolution(true)},
		},
	}
	for _, set := range data {
		result, err := res.Resolve(v, set.Ptr, set.Options...)
		if err != nil { // failed to resolve
			fmt.Printf("err: %s\n", err)
			continue
		}
		b, _ := json.Marshal(result)
		fmt.Printf("%s -> %s\n", set.Ptr, string(b))
	}

}
Output:

#/foo/0 -> "bar"
#/foo/1 -> "baz"
#/foo/2 -> "quux"
#/foo -> ["bar",{"$ref":"#/sub"},{"$ref":"obj2#/sub"}]
#/foo -> ["bar","baz","quux"]

Index

Examples

Constants

This section is empty.

Variables

View Source
var DefaultMaxRecursions = 10
View Source
var ErrMaxRecursion = errors.New("reached max number of recursions")
View Source
var ErrReferenceLoop = errors.New("reference loop detected")

Functions

This section is empty.

Types

type Option

type Option = option.Interface

func WithRecursiveResolution

func WithRecursiveResolution(b bool) Option

WithRecursiveResolution allows ou to enable recursive resolution on the *result* data structure. This means that after resolving the JSON reference in the structure at hand, it does another pass at resolving the entire data structure. Depending on your structure and size, this may incur significant cost.

Please note that recursive resolution of the result is still experimental. If you find problems, please submit a pull request with a failing test case.

type Provider

type Provider interface {
	Get(*url.URL) (interface{}, error)
}

Provider resolves a URL into a ... thing.

type Resolver

type Resolver struct {
	MaxRecursions int
	// contains filtered or unexported fields
}

Resolver is responsible for interpreting the provided JSON reference.

func New

func New() *Resolver

New creates a new Resolver

func (*Resolver) AddProvider

func (r *Resolver) AddProvider(p Provider) error

AddProvider adds a new Provider to be searched for in case a JSON pointer with more than just the URI fragment is given.

func (*Resolver) Resolve

func (r *Resolver) Resolve(v interface{}, ptr string, options ...Option) (ret interface{}, err error)

Resolve takes a target `v`, and a JSON pointer `spec`. spec is expected to be in the form of

[scheme://[userinfo@]host/path[?query]]#fragment
[scheme:opaque[?query]]#fragment

where everything except for `#fragment` is optional. If the fragment is empty, an error is returned.

If `spec` is the empty string, `v` is returned This method handles recursive JSON references.

If `WithRecursiveResolution` option is given and its value is true, an attempt to resolve all references within the resulting object is made by traversing the structure recursively. Default is false

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL