Comparison

teal-src/util/jsonschema.tl @ 11460:a8b4e04bc044

util.jsonschema: Rename types for improved readability
author Kim Alvefur <zash@zash.se>
date Thu, 18 Mar 2021 23:57:03 +0100
parent 11459:86904555bffc
child 12132:4ff0d33dfb2b
comparison
equal deleted inserted replaced
11459:86904555bffc 11460:a8b4e04bc044
6 -- Based on 6 -- Based on
7 -- https://json-schema.org/draft/2020-12/json-schema-core.html 7 -- https://json-schema.org/draft/2020-12/json-schema-core.html
8 -- https://json-schema.org/draft/2020-12/json-schema-validation.html 8 -- https://json-schema.org/draft/2020-12/json-schema-validation.html
9 -- 9 --
10 10
11 local record schema_t 11 local json = require"util.json"
12 enum type_e 12 local null = json.null;
13 "null" 13
14 "boolean" 14 local type json_type_name = json.json_type_name
15 "object" 15
16 "array" 16 -- json_type_name here is non-standard
17 "number" 17 local type schema_t = boolean | json_type_name | json_schema_object
18 "string" 18
19 "integer" 19 local record json_schema_object
20 end 20 type json_type_name = json.json_type_name
21 21 type schema_object = json_schema_object
22 type : type_e 22
23 type : json_type_name
23 enum : { any } 24 enum : { any }
24 const : any 25 const : any
25 26
26 allOf : { schema_t } 27 allOf : { schema_t }
27 anyOf : { schema_t } 28 anyOf : { schema_t }
54 uniqueItems : boolean 55 uniqueItems : boolean
55 maxContains : integer 56 maxContains : integer
56 minContains : integer 57 minContains : integer
57 58
58 -- objects 59 -- objects
59 properties : { string : schema_t | type_e } 60 properties : { string : schema_t }
60 maxProperties : integer 61 maxProperties : integer
61 minProperties : integer 62 minProperties : integer
62 required : { string } 63 required : { string }
63 dependentRequired : { string : { string } } 64 dependentRequired : { string : { string } }
64 additionalProperties: schema_t 65 additionalProperties: schema_t
85 title : string 86 title : string
86 description : string 87 description : string
87 deprecated : boolean 88 deprecated : boolean
88 readOnly : boolean 89 readOnly : boolean
89 writeOnly : boolean 90 writeOnly : boolean
90 end 91
91 local type_e = schema_t.type_e 92 -- methods
93 validate : function ( schema_t, any) : boolean
94 end
92 95
93 -- TODO validator function per schema property 96 -- TODO validator function per schema property
94 97
95 local type_validators : { type_e : function (schema_t, any) : boolean } = {} 98 local type_validators : { json_type_name : function (schema_t, any) : boolean } = {}
96 99
97 local function simple_validate(schema : type_e, data : any) : boolean 100 local function simple_validate(schema : json_type_name, data : any) : boolean
98 if schema == "object" and data is table then 101 if schema == "object" and data is table then
99 return type(data) == "table" and (next(data)==nil or type((next(data, nil))) == "string") 102 return type(data) == "table" and (next(data)==nil or type((next(data, nil))) == "string")
100 elseif schema == "array" and data is table then 103 elseif schema == "array" and data is table then
101 return type(data) == "table" and (next(data)==nil or type((next(data, nil))) == "number") 104 return type(data) == "table" and (next(data)==nil or type((next(data, nil))) == "number")
102 elseif schema == "integer" then 105 elseif schema == "integer" then
103 return math.type(data) == schema 106 return math.type(data) == schema
107 elseif schema == "null" then
108 return data == null
104 else 109 else
105 return type(data) == schema 110 return type(data) == schema
106 end 111 end
107 end 112 end
108 113
109 type_validators.string = function (schema : schema_t, data : any) : boolean 114 type_validators.string = function (schema : json_schema_object, data : any) : boolean
110 -- XXX this is measured in byte, while JSON measures in ... bork 115 -- XXX this is measured in byte, while JSON measures in ... bork
111 -- TODO use utf8.len? 116 -- TODO use utf8.len?
112 if data is string then 117 if data is string then
113 if schema.maxLength and #data > schema.maxLength then 118 if schema.maxLength and #data > schema.maxLength then
114 return false 119 return false
119 return true 124 return true
120 end 125 end
121 return false 126 return false
122 end 127 end
123 128
124 type_validators.number = function (schema : schema_t, data : number) : boolean 129 type_validators.number = function (schema : json_schema_object, data : number) : boolean
125 if schema.multipleOf and data % schema.multipleOf ~= 0 then 130 if schema.multipleOf and data % schema.multipleOf ~= 0 then
126 return false 131 return false
127 end 132 end
128 133
129 if schema.maximum and not ( data <= schema.maximum ) then 134 if schema.maximum and not ( data <= schema.maximum ) then
145 return true 150 return true
146 end 151 end
147 152
148 type_validators.integer = type_validators.number 153 type_validators.integer = type_validators.number
149 154
150 local function validate(schema : schema_t | type_e | boolean, data : any) : boolean 155 local function validate(schema : schema_t, data : any) : boolean
151 if schema is boolean then 156 if schema is boolean then
152 return schema 157 return schema
153 end 158 end
154 if schema is type_e then 159 if schema is json_type_name then
155 return simple_validate(schema, data) 160 return simple_validate(schema, data)
156 end 161 end
157 if schema is schema_t then 162 if schema is json_schema_object then
158 if schema.allOf then 163 if schema.allOf then
159 for _, sub in ipairs(schema.allOf) do 164 for _, sub in ipairs(schema.allOf) do
160 if not validate(sub, data) then 165 if not validate(sub, data) then
161 return false 166 return false
162 end 167 end
226 end 231 end
227 return true 232 return true
228 end 233 end
229 end 234 end
230 235
231 type_validators.table = function (schema : schema_t, data : any) : boolean 236 type_validators.table = function (schema : json_schema_object, data : any) : boolean
232 if data is table then 237 if data is table then
233 238
234 if schema.maxItems and #data > schema.maxItems then 239 if schema.maxItems and #data > schema.maxItems then
235 return false 240 return false
236 end 241 end
246 end 251 end
247 end 252 end
248 end 253 end
249 254
250 if schema.properties then 255 if schema.properties then
251 local additional : schema_t | boolean = schema.additionalProperties or true 256 local additional : schema_t = schema.additionalProperties or true
252 for k, v in pairs(data) do 257 for k, v in pairs(data) do
253 if schema.propertyNames and not validate(schema.propertyNames, k) then 258 if schema.propertyNames and not validate(schema.propertyNames, k) then
254 return false 259 return false
255 end 260 end
256 local s = schema.properties[k as string] or additional as schema_t 261 local s = schema.properties[k as string] or additional
257 if not validate(s, v) then 262 if not validate(s, v) then
258 return false 263 return false
259 end 264 end
260 end 265 end
261 elseif schema.additionalProperties then 266 elseif schema.additionalProperties then
343 return type_validators.table(schema, data) 348 return type_validators.table(schema, data)
344 end 349 end
345 return false 350 return false
346 end 351 end
347 352
348 return { 353 json_schema_object.validate = validate;
349 validate = validate; 354
350 schema_t = schema_t; 355 return json_schema_object;
351 }