Skip to content

Commit 74428e2

Browse files
example: add bytecount vocab
1 parent 98b9747 commit 74428e2

File tree

1 file changed

+149
-0
lines changed

1 file changed

+149
-0
lines changed

example_vocab_bytecount_test.go

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package jsonschema_test
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"log"
7+
"strconv"
8+
"strings"
9+
10+
"github.com/santhosh-tekuri/jsonschema/v6"
11+
"golang.org/x/text/message"
12+
)
13+
14+
// SchemaExt --
15+
16+
type ByteCount struct {
17+
maxBytes *int
18+
minBytes *int
19+
}
20+
21+
func (s *ByteCount) Validate(ctx *jsonschema.ValidatorContext, v any) {
22+
str, ok := v.(string)
23+
if !ok {
24+
return
25+
}
26+
if s.maxBytes != nil && len(str) > *s.maxBytes {
27+
ctx.AddError(&MaxBytes{Got: len(str), Want: *s.maxBytes})
28+
}
29+
if s.minBytes != nil && len(str) < *s.minBytes {
30+
ctx.AddError(&MinBytes{Got: len(str), Want: *s.maxBytes})
31+
}
32+
}
33+
34+
// Vocab --
35+
36+
func ByteCountVocab() *jsonschema.Vocabulary {
37+
url := "http://example.com/meta/byte-count"
38+
schema, err := jsonschema.UnmarshalJSON(strings.NewReader(`{
39+
"properties": {
40+
"maxBytes": { "type": "integer", "minimum": 0 },
41+
"minBytes": { "type": "integer", "minimum": 0 }
42+
}
43+
}`))
44+
if err != nil {
45+
log.Fatal(err)
46+
}
47+
48+
c := jsonschema.NewCompiler()
49+
if err := c.AddResource(url, schema); err != nil {
50+
log.Fatal(err)
51+
}
52+
sch, err := c.Compile(url)
53+
if err != nil {
54+
log.Fatal(err)
55+
}
56+
57+
return &jsonschema.Vocabulary{
58+
URL: url,
59+
Schema: sch,
60+
Compile: compileByteCount,
61+
}
62+
}
63+
64+
func numValue(obj map[string]any, prop string) *int {
65+
v, ok := obj[prop]
66+
if !ok {
67+
return nil
68+
}
69+
switch v.(type) {
70+
case json.Number, float32, float64, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
71+
if n, err := strconv.Atoi(fmt.Sprint(v)); err == nil {
72+
return &n
73+
}
74+
}
75+
return nil
76+
}
77+
78+
func compileByteCount(ctx *jsonschema.CompilerContext, obj map[string]any) (jsonschema.SchemaExt, error) {
79+
max := numValue(obj, "maxBytes")
80+
min := numValue(obj, "minBytes")
81+
if max == nil && min == nil {
82+
return nil, nil
83+
}
84+
return &ByteCount{maxBytes: max, minBytes: min}, nil
85+
}
86+
87+
// ErrorKind --
88+
89+
type MaxBytes struct {
90+
Got, Want int
91+
}
92+
93+
func (*MaxBytes) KeywordPath() []string {
94+
return []string{"maxBytes"}
95+
}
96+
97+
func (k *MaxBytes) LocalizedString(p *message.Printer) string {
98+
return p.Sprintf("maxBytes: got %d, want %d", k.Got, k.Want)
99+
}
100+
101+
type MinBytes struct {
102+
Got, Want int
103+
}
104+
105+
func (*MinBytes) KeywordPath() []string {
106+
return []string{"minBytes"}
107+
}
108+
109+
func (k *MinBytes) LocalizedString(p *message.Printer) string {
110+
return p.Sprintf("minBytes: got %d, want %d", k.Got, k.Want)
111+
}
112+
113+
// Example --
114+
115+
func Example_vocab_bytecount() {
116+
schema, err := jsonschema.UnmarshalJSON(strings.NewReader(`{
117+
"properties": {
118+
"name": {
119+
"type": "string",
120+
"maxBytes": 5
121+
}
122+
}
123+
}`))
124+
if err != nil {
125+
log.Fatal(err)
126+
}
127+
inst, err := jsonschema.UnmarshalJSON(strings.NewReader(`
128+
{ "name": "helloworld" }
129+
`))
130+
if err != nil {
131+
log.Fatal(err)
132+
}
133+
134+
c := jsonschema.NewCompiler()
135+
c.AssertVocabs()
136+
c.RegisterVocabulary(ByteCountVocab())
137+
if err := c.AddResource("schema.json", schema); err != nil {
138+
log.Fatal(err)
139+
}
140+
sch, err := c.Compile("schema.json")
141+
if err != nil {
142+
log.Fatal(err)
143+
}
144+
145+
err = sch.Validate(inst)
146+
fmt.Println("valid:", err == nil)
147+
// Output:
148+
// valid: false
149+
}

0 commit comments

Comments
 (0)