Fix the dependency issue (#231)

This commit is contained in:
Robbie Zhang
2018-06-21 12:09:42 -07:00
committed by GitHub
parent 027b76651d
commit 6ec1098bb8
16629 changed files with 74837 additions and 4975021 deletions

View File

@@ -1,8 +0,0 @@
# gojsonpointer
An implementation of JSON Pointer - Go language
## References
http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
### Note
The 4.Evaluation part of the previous reference, starting with 'If the currently referenced value is a JSON array, the reference token MUST contain either...' is not implemented.

View File

@@ -90,6 +90,13 @@ func (p *JsonPointer) Set(document interface{}, value interface{}) (interface{},
}
// Uses the pointer to delete a value from a JSON document
func (p *JsonPointer) Delete(document interface{}) (interface{}, error) {
is := &implStruct{mode: "DEL", inDocument: document}
p.implementation(is)
return document, is.outError
}
// Both Get and Set functions use the same implementation to avoid code duplication
func (p *JsonPointer) implementation(i *implStruct) {
@@ -106,9 +113,14 @@ func (p *JsonPointer) implementation(i *implStruct) {
node := i.inDocument
previousNodes := make([]interface{}, len(p.referenceTokens))
previousTokens := make([]string, len(p.referenceTokens))
for ti, token := range p.referenceTokens {
isLastToken := ti == len(p.referenceTokens)-1
previousNodes[ti] = node
previousTokens[ti] = token
switch v := node.(type) {
@@ -118,7 +130,11 @@ func (p *JsonPointer) implementation(i *implStruct) {
node = v[decodedToken]
if isLastToken && i.mode == "SET" {
v[decodedToken] = i.setInValue
} else if isLastToken && i.mode =="DEL" {
delete(v,decodedToken)
}
} else if (isLastToken && i.mode == "SET") {
v[decodedToken] = i.setInValue
} else {
i.outError = fmt.Errorf("Object has no key '%s'", decodedToken)
i.getOutKind = reflect.Map
@@ -144,6 +160,11 @@ func (p *JsonPointer) implementation(i *implStruct) {
node = v[tokenIndex]
if isLastToken && i.mode == "SET" {
v[tokenIndex] = i.setInValue
} else if isLastToken && i.mode =="DEL" {
v[tokenIndex] = v[len(v)-1]
v[len(v)-1] = nil
v = v[:len(v)-1]
previousNodes[ti-1].(map[string]interface{})[previousTokens[ti-1]] = v
}
default:

View File

@@ -1,247 +0,0 @@
// Copyright 2015 xeipuuv ( https://github.com/xeipuuv )
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// author xeipuuv
// author-github https://github.com/xeipuuv
// author-mail xeipuuv@gmail.com
//
// repository-name gojsonpointer
// repository-desc An implementation of JSON Pointer - Go language
//
// description Automated tests on package.
//
// created 03-03-2013
package gojsonpointer
import (
"encoding/json"
"testing"
)
const (
TEST_DOCUMENT_NB_ELEMENTS = 13
TEST_NODE_OBJ_NB_ELEMENTS = 4
TEST_DOCUMENT_STRING = `{
"foo": ["bar", "baz"],
"obj": { "a":1, "b":2, "c":[3,4], "d":[ {"e":9}, {"f":[50,51]} ] },
"": 0,
"a/b": 1,
"c%d": 2,
"e^f": 3,
"g|h": 4,
"i\\j": 5,
"k\"l": 6,
" ": 7,
"m~n": 8,
"o~/p": 9,
"q/~r": 10
}`
)
var testDocumentJson interface{}
func init() {
json.Unmarshal([]byte(TEST_DOCUMENT_STRING), &testDocumentJson)
}
func TestEscaping(t *testing.T) {
ins := []string{`/`, `/`, `/a~1b`, `/a~1b`, `/c%d`, `/e^f`, `/g|h`, `/i\j`, `/k"l`, `/ `, `/m~0n`, `/o~0~1p`, `/q~1~0r`}
outs := []float64{0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
for i := range ins {
p, err := NewJsonPointer(ins[i])
if err != nil {
t.Errorf("NewJsonPointer(%v) error %v", ins[i], err.Error())
}
s := p.String()
if s != ins[i] {
t.Errorf("\"%v\" -> \"%v\"", ins[i], s)
}
result, _, err := p.Get(testDocumentJson)
if err != nil {
t.Errorf("Get(%v) error %v", ins[i], err.Error())
}
if result != outs[i] {
t.Errorf("Get(%v) = %v, expect %v", ins[i], result, outs[i])
}
}
}
func BenchmarkParse(b *testing.B) {
for i := 0; i < b.N; i++ {
NewJsonPointer(`/definitions/simple/0/next`)
}
}
func BenchmarkParseWithEscape(b *testing.B) {
for i := 0; i < b.N; i++ {
NewJsonPointer(`/definiti~0ons/simple/0/next`)
}
}
func BenchmarkString(b *testing.B) {
p, _ := NewJsonPointer(`/definitions/simple/0/next`)
b.ResetTimer()
for i := 0; i < b.N; i++ {
p.String()
}
}
func BenchmarkStringWithEscape(b *testing.B) {
p, _ := NewJsonPointer(`/definiti~0ons/simple/0/next`)
b.ResetTimer()
for i := 0; i < b.N; i++ {
p.String()
}
}
func TestFullDocument(t *testing.T) {
in := ``
p, err := NewJsonPointer(in)
if err != nil {
t.Errorf("NewJsonPointer(%v) error %v", in, err.Error())
}
result, _, err := p.Get(testDocumentJson)
if err != nil {
t.Errorf("Get(%v) error %v", in, err.Error())
}
if len(result.(map[string]interface{})) != TEST_DOCUMENT_NB_ELEMENTS {
t.Errorf("Get(%v) = %v, expect full document", in, result)
}
}
func TestGetNode(t *testing.T) {
in := `/obj`
p, err := NewJsonPointer(in)
if err != nil {
t.Errorf("NewJsonPointer(%v) error %v", in, err.Error())
}
result, _, err := p.Get(testDocumentJson)
if err != nil {
t.Errorf("Get(%v) error %v", in, err.Error())
}
if len(result.(map[string]interface{})) != TEST_NODE_OBJ_NB_ELEMENTS {
t.Errorf("Get(%v) = %v, expect full document", in, result)
}
}
func BenchmarkGet(b *testing.B) {
p, _ := NewJsonPointer(`/obj/d/1/f`)
b.ResetTimer()
for i := 0; i < b.N; i++ {
p.Get(testDocumentJson)
}
}
func TestArray(t *testing.T) {
ins := []string{`/foo/0`, `/foo/0`, `/foo/1`}
outs := []string{"bar", "bar", "baz"}
for i := range ins {
p, err := NewJsonPointer(ins[i])
if err != nil {
t.Errorf("NewJsonPointer(%v) error %v", ins[i], err.Error())
}
result, _, err := p.Get(testDocumentJson)
if err != nil {
t.Errorf("Get(%v) error %v", ins[i], err.Error())
}
if result != outs[i] {
t.Errorf("Get(%v) = %v, expect %v", ins[i], result, outs[i])
}
}
}
func TestObject(t *testing.T) {
ins := []string{`/obj/a`, `/obj/b`, `/obj/c/0`, `/obj/c/1`, `/obj/c/1`, `/obj/d/1/f/0`}
outs := []float64{1, 2, 3, 4, 4, 50}
for i := range ins {
p, err := NewJsonPointer(ins[i])
if err != nil {
t.Errorf("NewJsonPointer(%v) error %v", ins[i], err.Error())
}
result, _, err := p.Get(testDocumentJson)
if err != nil {
t.Errorf("Get(%v) error %v", ins[i], err.Error())
}
if result != outs[i] {
t.Errorf("Get(%v) = %v, expect %v", ins[i], result, outs[i])
}
}
}
func TestSetNode(t *testing.T) {
jsonText := `{"a":[{"b": 1, "c": 2}], "d": 3}`
var jsonDocument interface{}
json.Unmarshal([]byte(jsonText), &jsonDocument)
in := "/a/0/c"
p, err := NewJsonPointer(in)
if err != nil {
t.Errorf("NewJsonPointer(%v) error %v", in, err.Error())
}
_, err = p.Set(jsonDocument, 999)
if err != nil {
t.Errorf("Set(%v) error %v", in, err.Error())
}
firstNode := jsonDocument.(map[string]interface{})
if len(firstNode) != 2 {
t.Errorf("Set(%s) failed", in)
}
sliceNode := firstNode["a"].([]interface{})
if len(sliceNode) != 1 {
t.Errorf("Set(%s) failed", in)
}
changedNode := sliceNode[0].(map[string]interface{})
changedNodeValue := changedNode["c"].(int)
if changedNodeValue != 999 {
if len(sliceNode) != 1 {
t.Errorf("Set(%s) failed", in)
}
}
}

View File

@@ -1,10 +0,0 @@
# gojsonreference
An implementation of JSON Reference - Go language
## Dependencies
https://github.com/xeipuuv/gojsonpointer
## References
http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03

View File

@@ -27,11 +27,12 @@ package gojsonreference
import (
"errors"
"github.com/xeipuuv/gojsonpointer"
"net/url"
"path/filepath"
"runtime"
"strings"
"github.com/xeipuuv/gojsonpointer"
)
const (
@@ -124,16 +125,21 @@ func (r *JsonReference) parse(jsonReferenceString string) (err error) {
// Creates a new reference from a parent and a child
// If the child cannot inherit from the parent, an error is returned
func (r *JsonReference) Inherits(child JsonReference) (*JsonReference, error) {
childUrl := child.GetUrl()
parentUrl := r.GetUrl()
if childUrl == nil {
if child.GetUrl() == nil {
return nil, errors.New("childUrl is nil!")
}
if parentUrl == nil {
if r.GetUrl() == nil {
return nil, errors.New("parentUrl is nil!")
}
ref, err := NewJsonReference(parentUrl.ResolveReference(childUrl).String())
// Get a copy of the parent url to make sure we do not modify the original.
// URL reference resolving fails if the fragment of the child is empty, but the parent's is not.
// The fragment of the child must be used, so the fragment of the parent is manually removed.
parentUrl := *r.GetUrl()
parentUrl.Fragment = ""
ref, err := NewJsonReference(parentUrl.ResolveReference(child.GetUrl()).String())
if err != nil {
return nil, err
}

View File

@@ -1,378 +0,0 @@
// Copyright 2015 xeipuuv ( https://github.com/xeipuuv )
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// author xeipuuv
// author-github https://github.com/xeipuuv
// author-mail xeipuuv@gmail.com
//
// repository-name gojsonreference
// repository-desc An implementation of JSON Reference - Go language
//
// description Automated tests on package.
//
// created 03-03-2013
package gojsonreference
import (
"testing"
)
func TestFull(t *testing.T) {
in := "http://host/path/a/b/c#/f/a/b"
r1, err := NewJsonReference(in)
if err != nil {
t.Errorf("NewJsonReference(%v) error %s", in, err.Error())
}
if in != r1.String() {
t.Errorf("NewJsonReference(%v) = %v, expect %v", in, r1.String(), in)
}
if r1.HasFragmentOnly != false {
t.Errorf("NewJsonReference(%v)::HasFragmentOnly %v expect %v", in, r1.HasFragmentOnly, false)
}
if r1.HasFullUrl != true {
t.Errorf("NewJsonReference(%v)::HasFullUrl %v expect %v", in, r1.HasFullUrl, true)
}
if r1.HasUrlPathOnly != false {
t.Errorf("NewJsonReference(%v)::HasUrlPathOnly %v expect %v", in, r1.HasUrlPathOnly, false)
}
if r1.HasFileScheme != false {
t.Errorf("NewJsonReference(%v)::HasFileScheme %v expect %v", in, r1.HasFileScheme, false)
}
if r1.GetPointer().String() != "/f/a/b" {
t.Errorf("NewJsonReference(%v)::GetPointer() %v expect %v", in, r1.GetPointer().String(), "/f/a/b")
}
}
func TestFullUrl(t *testing.T) {
in := "http://host/path/a/b/c"
r1, err := NewJsonReference(in)
if err != nil {
t.Errorf("NewJsonReference(%v) error %s", in, err.Error())
}
if in != r1.String() {
t.Errorf("NewJsonReference(%v) = %v, expect %v", in, r1.String(), in)
}
if r1.HasFragmentOnly != false {
t.Errorf("NewJsonReference(%v)::HasFragmentOnly %v expect %v", in, r1.HasFragmentOnly, false)
}
if r1.HasFullUrl != true {
t.Errorf("NewJsonReference(%v)::HasFullUrl %v expect %v", in, r1.HasFullUrl, true)
}
if r1.HasUrlPathOnly != false {
t.Errorf("NewJsonReference(%v)::HasUrlPathOnly %v expect %v", in, r1.HasUrlPathOnly, false)
}
if r1.HasFileScheme != false {
t.Errorf("NewJsonReference(%v)::HasFileScheme %v expect %v", in, r1.HasFileScheme, false)
}
if r1.GetPointer().String() != "" {
t.Errorf("NewJsonReference(%v)::GetPointer() %v expect %v", in, r1.GetPointer().String(), "")
}
}
func TestFragmentOnly(t *testing.T) {
in := "#/fragment/only"
r1, err := NewJsonReference(in)
if err != nil {
t.Errorf("NewJsonReference(%v) error %s", in, err.Error())
}
if in != r1.String() {
t.Errorf("NewJsonReference(%v) = %v, expect %v", in, r1.String(), in)
}
if r1.HasFragmentOnly != true {
t.Errorf("NewJsonReference(%v)::HasFragmentOnly %v expect %v", in, r1.HasFragmentOnly, true)
}
if r1.HasFullUrl != false {
t.Errorf("NewJsonReference(%v)::HasFullUrl %v expect %v", in, r1.HasFullUrl, false)
}
if r1.HasUrlPathOnly != false {
t.Errorf("NewJsonReference(%v)::HasUrlPathOnly %v expect %v", in, r1.HasUrlPathOnly, false)
}
if r1.HasFileScheme != false {
t.Errorf("NewJsonReference(%v)::HasFileScheme %v expect %v", in, r1.HasFileScheme, false)
}
if r1.GetPointer().String() != "/fragment/only" {
t.Errorf("NewJsonReference(%v)::GetPointer() %v expect %v", in, r1.GetPointer().String(), "/fragment/only")
}
}
func TestUrlPathOnly(t *testing.T) {
in := "/documents/document.json"
r1, err := NewJsonReference(in)
if err != nil {
t.Errorf("NewJsonReference(%v) error %s", in, err.Error())
}
if in != r1.String() {
t.Errorf("NewJsonReference(%v) = %v, expect %v", in, r1.String(), in)
}
if r1.HasFragmentOnly != false {
t.Errorf("NewJsonReference(%v)::HasFragmentOnly %v expect %v", in, r1.HasFragmentOnly, false)
}
if r1.HasFullUrl != false {
t.Errorf("NewJsonReference(%v)::HasFullUrl %v expect %v", in, r1.HasFullUrl, false)
}
if r1.HasUrlPathOnly != true {
t.Errorf("NewJsonReference(%v)::HasUrlPathOnly %v expect %v", in, r1.HasUrlPathOnly, true)
}
if r1.HasFileScheme != false {
t.Errorf("NewJsonReference(%v)::HasFileScheme %v expect %v", in, r1.HasFileScheme, false)
}
if r1.GetPointer().String() != "" {
t.Errorf("NewJsonReference(%v)::GetPointer() %v expect %v", in, r1.GetPointer().String(), "")
}
}
func TestUrlRelativePathOnly(t *testing.T) {
in := "document.json"
r1, err := NewJsonReference(in)
if err != nil {
t.Errorf("NewJsonReference(%v) error %s", in, err.Error())
}
if in != r1.String() {
t.Errorf("NewJsonReference(%v) = %v, expect %v", in, r1.String(), in)
}
if r1.HasFragmentOnly != false {
t.Errorf("NewJsonReference(%v)::HasFragmentOnly %v expect %v", in, r1.HasFragmentOnly, false)
}
if r1.HasFullUrl != false {
t.Errorf("NewJsonReference(%v)::HasFullUrl %v expect %v", in, r1.HasFullUrl, false)
}
if r1.HasUrlPathOnly != true {
t.Errorf("NewJsonReference(%v)::HasUrlPathOnly %v expect %v", in, r1.HasUrlPathOnly, true)
}
if r1.HasFileScheme != false {
t.Errorf("NewJsonReference(%v)::HasFileScheme %v expect %v", in, r1.HasFileScheme, false)
}
if r1.GetPointer().String() != "" {
t.Errorf("NewJsonReference(%v)::GetPointer() %v expect %v", in, r1.GetPointer().String(), "")
}
}
func TestInheritsValid(t *testing.T) {
in1 := "http://www.test.com/doc.json"
in2 := "#/a/b"
out := in1 + in2
r1, _ := NewJsonReference(in1)
r2, _ := NewJsonReference(in2)
result, err := r1.Inherits(r2)
if err != nil {
t.Errorf("Inherits(%s,%s) error %s", r1.String(), r2.String(), err.Error())
}
if result.String() != out {
t.Errorf("Inherits(%s,%s) = %s, expect %s", r1.String(), r2.String(), result.String(), out)
}
if result.GetPointer().String() != "/a/b" {
t.Errorf("result(%v)::GetPointer() %v expect %v", result.String(), result.GetPointer().String(), "/a/b")
}
}
func TestInheritsDifferentHost(t *testing.T) {
in1 := "http://www.test.com/doc.json"
in2 := "http://www.test2.com/doc.json#bla"
r1, _ := NewJsonReference(in1)
r2, _ := NewJsonReference(in2)
result, err := r1.Inherits(r2)
if err != nil {
t.Errorf("Inherits(%s,%s) should not fail. Error: %s", r1.String(), r2.String(), err.Error())
}
if result.String() != in2 {
t.Errorf("Inherits(%s,%s) should be %s but is %s", in1, in2, in2, result)
}
if result.GetPointer().String() != "" {
t.Errorf("result(%v)::GetPointer() %v expect %v", result.String(), result.GetPointer().String(), "")
}
}
func TestFileScheme(t *testing.T) {
in1 := "file:///Users/mac/1.json#a"
in2 := "file:///Users/mac/2.json#b"
r1, _ := NewJsonReference(in1)
r2, _ := NewJsonReference(in2)
if r1.HasFragmentOnly != false {
t.Errorf("NewJsonReference(%v)::HasFragmentOnly %v expect %v", in1, r1.HasFragmentOnly, false)
}
if r1.HasFileScheme != true {
t.Errorf("NewJsonReference(%v)::HasFileScheme %v expect %v", in1, r1.HasFileScheme, true)
}
if r1.HasFullFilePath != true {
t.Errorf("NewJsonReference(%v)::HasFullFilePath %v expect %v", in1, r1.HasFullFilePath, true)
}
if r1.IsCanonical() != true {
t.Errorf("NewJsonReference(%v)::IsCanonical %v expect %v", in1, r1.IsCanonical, true)
}
result, err := r1.Inherits(r2)
if err != nil {
t.Errorf("Inherits(%s,%s) should not fail. Error: %s", r1.String(), r2.String(), err.Error())
}
if result.String() != in2 {
t.Errorf("Inherits(%s,%s) should be %s but is %s", in1, in2, in2, result)
}
if result.GetPointer().String() != "" {
t.Errorf("result(%v)::GetPointer() %v expect %v", result.String(), result.GetPointer().String(), "")
}
}
func TestReferenceResolution(t *testing.T) {
// 5.4. Reference Resolution Examples
// http://tools.ietf.org/html/rfc3986#section-5.4
base := "http://a/b/c/d;p?q"
baseRef, err := NewJsonReference(base)
if err != nil {
t.Errorf("NewJsonReference(%s) failed error: %s", base, err.Error())
}
if baseRef.String() != base {
t.Errorf("NewJsonReference(%s) %s expected %s", base, baseRef.String(), base)
}
checks := []string{
// 5.4.1. Normal Examples
// http://tools.ietf.org/html/rfc3986#section-5.4.1
"g:h", "g:h",
"g", "http://a/b/c/g",
"./g", "http://a/b/c/g",
"g/", "http://a/b/c/g/",
"/g", "http://a/g",
"//g", "http://g",
"?y", "http://a/b/c/d;p?y",
"g?y", "http://a/b/c/g?y",
"#s", "http://a/b/c/d;p?q#s",
"g#s", "http://a/b/c/g#s",
"g?y#s", "http://a/b/c/g?y#s",
";x", "http://a/b/c/;x",
"g;x", "http://a/b/c/g;x",
"g;x?y#s", "http://a/b/c/g;x?y#s",
"", "http://a/b/c/d;p?q",
".", "http://a/b/c/",
"./", "http://a/b/c/",
"..", "http://a/b/",
"../", "http://a/b/",
"../g", "http://a/b/g",
"../..", "http://a/",
"../../", "http://a/",
"../../g", "http://a/g",
// 5.4.2. Abnormal Examples
// http://tools.ietf.org/html/rfc3986#section-5.4.2
"../../../g", "http://a/g",
"../../../../g", "http://a/g",
"/./g", "http://a/g",
"/../g", "http://a/g",
"g.", "http://a/b/c/g.",
".g", "http://a/b/c/.g",
"g..", "http://a/b/c/g..",
"..g", "http://a/b/c/..g",
"./../g", "http://a/b/g",
"./g/.", "http://a/b/c/g/",
"g/./h", "http://a/b/c/g/h",
"g/../h", "http://a/b/c/h",
"g;x=1/./y", "http://a/b/c/g;x=1/y",
"g;x=1/../y", "http://a/b/c/y",
"g?y/./x", "http://a/b/c/g?y/./x",
"g?y/../x", "http://a/b/c/g?y/../x",
"g#s/./x", "http://a/b/c/g#s/./x",
"g#s/../x", "http://a/b/c/g#s/../x",
"http:g", "http:g", // for strict parsers
//"http:g", "http://a/b/c/g", // for backward compatibility
}
for i := 0; i < len(checks); i += 2 {
child := checks[i]
expected := checks[i+1]
// fmt.Printf("%d: %v -> %v\n", i/2, child, expected)
childRef, e := NewJsonReference(child)
if e != nil {
t.Errorf("%d: NewJsonReference(%s) failed error: %s", i/2, child, e.Error())
}
res, e := baseRef.Inherits(childRef)
if res == nil {
t.Errorf("%d: Inherits(%s, %s) nil not expected", i/2, base, child)
}
if e != nil {
t.Errorf("%d: Inherits(%s) failed error: %s", i/2, child, e.Error())
}
if res.String() != expected {
t.Errorf("%d: Inherits(%s, %s) %s expected %s", i/2, base, child, res.String(), expected)
}
}
}

View File

@@ -1 +0,0 @@
*.sw[nop]

View File

@@ -1,7 +0,0 @@
language: go
go:
- 1.3
before_install:
- go get github.com/sigu-399/gojsonreference
- go get github.com/sigu-399/gojsonpointer
- go get github.com/stretchr/testify/assert

View File

@@ -1,257 +0,0 @@
[![Build Status](https://travis-ci.org/xeipuuv/gojsonschema.svg)](https://travis-ci.org/xeipuuv/gojsonschema)
# gojsonschema
## Description
An implementation of JSON Schema, based on IETF's draft v4 - Go language
References :
* http://json-schema.org
* http://json-schema.org/latest/json-schema-core.html
* http://json-schema.org/latest/json-schema-validation.html
## Installation
```
go get github.com/xeipuuv/gojsonschema
```
Dependencies :
* [github.com/xeipuuv/gojsonpointer](https://github.com/xeipuuv/gojsonpointer)
* [github.com/xeipuuv/gojsonreference](https://github.com/xeipuuv/gojsonreference)
* [github.com/stretchr/testify/assert](https://github.com/stretchr/testify#assert-package)
## Usage
### Example
```go
package main
import (
"fmt"
"github.com/xeipuuv/gojsonschema"
)
func main() {
schemaLoader := gojsonschema.NewReferenceLoader("file:///home/me/schema.json")
documentLoader := gojsonschema.NewReferenceLoader("file:///home/me/document.json")
result, err := gojsonschema.Validate(schemaLoader, documentLoader)
if err != nil {
panic(err.Error())
}
if result.Valid() {
fmt.Printf("The document is valid\n")
} else {
fmt.Printf("The document is not valid. see errors :\n")
for _, desc := range result.Errors() {
fmt.Printf("- %s\n", desc)
}
}
}
```
#### Loaders
There are various ways to load your JSON data.
In order to load your schemas and documents,
first declare an appropriate loader :
* Web / HTTP, using a reference :
```go
loader := gojsonschema.NewReferenceLoader("http://www.some_host.com/schema.json")
```
* Local file, using a reference :
```go
loader := gojsonschema.NewReferenceLoader("file:///home/me/schema.json")
```
References use the URI scheme, the prefix (file://) and a full path to the file are required.
* JSON strings :
```go
loader := gojsonschema.NewStringLoader(`{"type": "string"}`)
```
* Custom Go types :
```go
m := map[string]interface{}{"type": "string"}
loader := gojsonschema.NewGoLoader(m)
```
And
```go
type Root struct {
Users []User `json:"users"`
}
type User struct {
Name string `json:"name"`
}
...
data := Root{}
data.Users = append(data.Users, User{"John"})
data.Users = append(data.Users, User{"Sophia"})
data.Users = append(data.Users, User{"Bill"})
loader := gojsonschema.NewGoLoader(data)
```
#### Validation
Once the loaders are set, validation is easy :
```go
result, err := gojsonschema.Validate(schemaLoader, documentLoader)
```
Alternatively, you might want to load a schema only once and process to multiple validations :
```go
schema, err := gojsonschema.NewSchema(schemaLoader)
...
result1, err := schema.Validate(documentLoader1)
...
result2, err := schema.Validate(documentLoader2)
...
// etc ...
```
To check the result :
```go
if result.Valid() {
fmt.Printf("The document is valid\n")
} else {
fmt.Printf("The document is not valid. see errors :\n")
for _, err := range result.Errors() {
// Err implements the ResultError interface
fmt.Printf("- %s\n", err)
}
}
```
## Working with Errors
The library handles string error codes which you can customize by creating your own gojsonschema.locale and setting it
```go
gojsonschema.Locale = YourCustomLocale{}
```
However, each error contains additional contextual information.
**err.Type()**: *string* Returns the "type" of error that occurred. Note you can also type check. See below
Note: An error of RequiredType has an err.Type() return value of "required"
"required": RequiredError
"invalid_type": InvalidTypeError
"number_any_of": NumberAnyOfError
"number_one_of": NumberOneOfError
"number_all_of": NumberAllOfError
"number_not": NumberNotError
"missing_dependency": MissingDependencyError
"internal": InternalError
"enum": EnumError
"array_no_additional_items": ArrayNoAdditionalItemsError
"array_min_items": ArrayMinItemsError
"array_max_items": ArrayMaxItemsError
"unique": ItemsMustBeUniqueError
"array_min_properties": ArrayMinPropertiesError
"array_max_properties": ArrayMaxPropertiesError
"additional_property_not_allowed": AdditionalPropertyNotAllowedError
"invalid_property_pattern": InvalidPropertyPatternError
"string_gte": StringLengthGTEError
"string_lte": StringLengthLTEError
"pattern": DoesNotMatchPatternError
"multiple_of": MultipleOfError
"number_gte": NumberGTEError
"number_gt": NumberGTError
"number_lte": NumberLTEError
"number_lt": NumberLTError
**err.Value()**: *interface{}* Returns the value given
**err.Context()**: *gojsonschema.jsonContext* Returns the context. This has a String() method that will print something like this: (root).firstName
**err.Field()**: *string* Returns the fieldname in the format firstName, or for embedded properties, person.firstName. This returns the same as the String() method on *err.Context()* but removes the (root). prefix.
**err.Description()**: *string* The error description. This is based on the locale you are using. See the beginning of this section for overwriting the locale with a custom implementation.
**err.Details()**: *gojsonschema.ErrorDetails* Returns a map[string]interface{} of additional error details specific to the error. For example, GTE errors will have a "min" value, LTE will have a "max" value. See errors.go for a full description of all the error details. Every error always contains a "field" key that holds the value of *err.Field()*
Note in most cases, the err.Details() will be used to generate replacement strings in your locales, and not used directly. These strings follow the text/template format i.e.
```
{{.field}} must be greater than or equal to {{.min}}
```
The library allows you to specify custom template functions, should you require more complex error message handling.
```go
gojsonschema.ErrorTemplateFuncs = map[string]interface{}{
"allcaps": func(s string) string {
return strings.ToUpper(s)
},
}
```
Given the above definition, you can use the custom function `"allcaps"` in your localization templates:
```
{{allcaps .field}} must be greater than or equal to {{.min}}
```
The above error message would then be rendered with the `field` value in capital letters. For example:
```
"PASSWORD must be greater than or equal to 8"
```
Learn more about what types of template functions you can use in `ErrorTemplateFuncs` by referring to Go's [text/template FuncMap](https://golang.org/pkg/text/template/#FuncMap) type.
## Formats
JSON Schema allows for optional "format" property to validate strings against well-known formats. gojsonschema ships with all of the formats defined in the spec that you can use like this:
````json
{"type": "string", "format": "email"}
````
Available formats: date-time, hostname, email, ipv4, ipv6, uri, uri-reference.
For repetitive or more complex formats, you can create custom format checkers and add them to gojsonschema like this:
```go
// Define the format checker
type RoleFormatChecker struct {}
// Ensure it meets the gojsonschema.FormatChecker interface
func (f RoleFormatChecker) IsFormat(input string) bool {
return strings.HasPrefix("ROLE_", input)
}
// Add it to the library
gojsonschema.FormatCheckers.Add("role", RoleFormatChecker{})
````
Now to use in your json schema:
````json
{"type": "string", "format": "role"}
````
## Uses
gojsonschema uses the following test suite :
https://github.com/json-schema/JSON-Schema-Test-Suite

View File

@@ -1,23 +0,0 @@
package gojsonschema
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestUUIDFormatCheckerIsFormat(t *testing.T) {
checker := UUIDFormatChecker{}
assert.True(t, checker.IsFormat("01234567-89ab-cdef-0123-456789abcdef"))
assert.True(t, checker.IsFormat("f1234567-89ab-cdef-0123-456789abcdef"))
assert.False(t, checker.IsFormat("not-a-uuid"))
assert.False(t, checker.IsFormat("g1234567-89ab-cdef-0123-456789abcdef"))
}
func TestURIReferenceFormatCheckerIsFormat(t *testing.T) {
checker := URIReferenceFormatChecker{}
assert.True(t, checker.IsFormat("relative"))
assert.True(t, checker.IsFormat("https://dummyhost.com/dummy-path?dummy-qp-name=dummy-qp-value"))
}

View File

@@ -1,12 +0,0 @@
package: github.com/xeipuuv/gojsonschema
license: Apache 2.0
import:
- package: github.com/xeipuuv/gojsonschema
- package: github.com/xeipuuv/gojsonpointer
- package: github.com/xeipuuv/gojsonreference
- package: github.com/stretchr/testify/assert
version: ^1.1.3

View File

@@ -1 +0,0 @@
[null,2,3,4]

View File

@@ -1 +0,0 @@
[null,2,3,"foo"]

View File

@@ -1 +0,0 @@
[1,2,3,4,5]

View File

@@ -1 +0,0 @@
[1,2,3,4,5]

View File

@@ -1 +0,0 @@
{"foo":"bar"}

View File

@@ -1 +0,0 @@
[1,"foo",false]

View File

@@ -1 +0,0 @@
{"additionalItems":{"type":"integer"},"items":[{}]}

View File

@@ -1 +0,0 @@
{"additionalItems":false,"items":{}}

View File

@@ -1 +0,0 @@
{"additionalItems":false,"items":[{},{},{}]}

View File

@@ -1 +0,0 @@
{"additionalItems":false}

View File

@@ -1 +0,0 @@
{"items":[{"type":"integer"}]}

View File

@@ -1 +0,0 @@
{"bar":2,"foo":1,"quux":"boom"}

View File

@@ -1 +0,0 @@
{"foo":1, "vroom": 2}

View File

@@ -1 +0,0 @@
{"bar":2,"foo":1,"quux":true}

View File

@@ -1 +0,0 @@
{"bar":2,"foo":1,"quux":12}

View File

@@ -1 +0,0 @@
{"bar":2,"foo":1,"quux":true}

View File

@@ -1 +0,0 @@
{"additionalProperties":false,"properties":{"bar":{},"foo":{}},"patternProperties": { "^v": {} }}

View File

@@ -1 +0,0 @@
{"additionalProperties":{"type":"boolean"},"properties":{"bar":{},"foo":{}}}

View File

@@ -1 +0,0 @@
{"properties":{"bar":{},"foo":{}}}

View File

@@ -1 +0,0 @@
{"bar":2,"foo":"baz"}

View File

@@ -1 +0,0 @@
{"foo":"baz"}

View File

@@ -1 +0,0 @@
{"bar":2}

View File

@@ -1 +0,0 @@
{"bar":"quux","foo":"baz"}

View File

@@ -1 +0,0 @@
{"bar":2,"baz":null,"foo":"quux"}

View File

@@ -1 +0,0 @@
{"baz":null,"foo":"quux"}

View File

@@ -1 +0,0 @@
{"bar":2,"baz":null}

View File

@@ -1 +0,0 @@
{"bar":2,"foo":"quux"}

View File

@@ -1 +0,0 @@
{"bar":2}

View File

@@ -1 +0,0 @@
{"allOf":[{"properties":{"bar":{"type":"integer"}},"required":["bar"]},{"properties":{"foo":{"type":"string"}},"required":["foo"]}]}

View File

@@ -1 +0,0 @@
{"allOf":[{"properties":{"foo":{"type":"string"}},"required":["foo"]},{"properties":{"baz":{"type":"null"}},"required":["baz"]}],"properties":{"bar":{"type":"integer"}},"required":["bar"]}

View File

@@ -1 +0,0 @@
{"allOf":[{"maximum":30},{"minimum":20}]}

View File

@@ -1 +0,0 @@
"foobar"

View File

@@ -1 +0,0 @@
"foo"

View File

@@ -1 +0,0 @@
{"anyOf":[{"type":"integer"},{"minimum":2}]}

View File

@@ -1 +0,0 @@
{"anyOf":[{"maxLength":2},{"minLength":4}],"type":"string"}

View File

@@ -1 +0,0 @@
{"definitions":{"foo":{"type":"integer"}}}

View File

@@ -1 +0,0 @@
{"definitions":{"foo":{"type":1}}}

View File

@@ -1 +0,0 @@
{"$ref":"http://json-schema.org/draft-04/schema#"}

View File

@@ -1 +0,0 @@
{"$ref":"http://json-schema.org/draft-04/schema#"}

View File

@@ -1 +0,0 @@
{"foo":1}

View File

@@ -1 +0,0 @@
{"bar":2,"foo":1}

View File

@@ -1 +0,0 @@
{"bar":2}

View File

@@ -1 +0,0 @@
{"bar":2,"foo":1}

View File

@@ -1 +0,0 @@
{"bar":2,"foo":1,"quux":3}

View File

@@ -1 +0,0 @@
{"foo":1,"quux":2}

View File

@@ -1 +0,0 @@
{"bar":1,"quux":2}

View File

@@ -1 +0,0 @@
{"quux":1}

View File

@@ -1 +0,0 @@
{"bar":2,"foo":1}

View File

@@ -1 +0,0 @@
{"foo":"quux"}

View File

@@ -1 +0,0 @@
{"bar":2,"foo":"quux"}

View File

@@ -1 +0,0 @@
{"bar":"quux","foo":2}

View File

@@ -1 +0,0 @@
{"bar":"quux","foo":"quux"}

View File

@@ -1 +0,0 @@
{"dependencies":{"bar":["foo"]}}

View File

@@ -1 +0,0 @@
{"dependencies":{"quux":["foo","bar"]}}

View File

@@ -1 +0,0 @@
{"dependencies":{"bar":{"properties":{"bar":{"type":"integer"},"foo":{"type":"integer"}}}}}

View File

@@ -1 +0,0 @@
null

View File

@@ -1 +0,0 @@
{"foo":false}

View File

@@ -1 +0,0 @@
{"enum":[1,2,3]}

View File

@@ -1 +0,0 @@
{"enum":[6,"foo",[],true,{"foo":12}]}

View File

@@ -1 +0,0 @@
"test"

View File

@@ -1 +0,0 @@
"test@"

View File

@@ -1 +0,0 @@
"test@test.com"

View File

@@ -1 +0,0 @@
"AB-10105"

View File

@@ -1 +0,0 @@
"ABC10105"

View File

@@ -1 +0,0 @@
"05:15:37"

View File

@@ -1 +0,0 @@
"2015-05-13"

View File

@@ -1 +0,0 @@
"2015-6-31"

View File

@@ -1 +0,0 @@
"2015-01-30 19:08:06"

View File

@@ -1 +0,0 @@
"18:31:24-05:00"

View File

@@ -1 +0,0 @@
"2002-10-02T10:00:00-05:00"

View File

@@ -1 +0,0 @@
"2002-10-02T15:00:00Z"

Some files were not shown because too many files have changed in this diff Show More