Software /
code /
prosody
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 } |