Software /
code /
prosody
Comparison
util/jsonschema.lua @ 12132:4ff0d33dfb2b
util.jsonschema: Add support for $ref pointers
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Wed, 29 Dec 2021 16:57:35 +0100 |
parent | 11460:a8b4e04bc044 |
child | 12500:88e1b94105ae |
comparison
equal
deleted
inserted
replaced
12131:b4c0efff8dd3 | 12132:4ff0d33dfb2b |
---|---|
1 local json = require("util.json") | 1 local json = require("util.json") |
2 local null = json.null; | 2 local null = json.null; |
3 | |
4 local pointer = require("util.jsonpointer") | |
3 | 5 |
4 local json_type_name = json.json_type_name | 6 local json_type_name = json.json_type_name |
5 | 7 |
6 local schema_t = {} | 8 local schema_t = {} |
7 | 9 |
61 return true | 63 return true |
62 end | 64 end |
63 | 65 |
64 type_validators.integer = type_validators.number | 66 type_validators.integer = type_validators.number |
65 | 67 |
66 local function validate(schema, data) | 68 local function validate(schema, data, root) |
67 if type(schema) == "boolean" then | 69 if type(schema) == "boolean" then |
68 return schema | 70 return schema |
69 end | 71 end |
70 if type(schema) == "string" then | 72 if type(schema) == "string" then |
71 return simple_validate(schema, data) | 73 return simple_validate(schema, data) |
72 end | 74 end |
73 if type(schema) == "table" then | 75 if type(schema) == "table" then |
76 if root == nil then | |
77 root = schema | |
78 end | |
79 if schema["$ref"] and schema["$ref"]:sub(1, 1) == "#" then | |
80 local referenced = pointer.resolve(root, schema["$ref"]:sub(2)) | |
81 if referenced ~= nil then | |
82 return validate(referenced, data, root) | |
83 end | |
84 end | |
85 | |
74 if schema.allOf then | 86 if schema.allOf then |
75 for _, sub in ipairs(schema.allOf) do | 87 for _, sub in ipairs(schema.allOf) do |
76 if not validate(sub, data) then | 88 if not validate(sub, data, root) then |
77 return false | 89 return false |
78 end | 90 end |
79 end | 91 end |
80 return true | 92 return true |
81 end | 93 end |
82 | 94 |
83 if schema.oneOf then | 95 if schema.oneOf then |
84 local valid = 0 | 96 local valid = 0 |
85 for _, sub in ipairs(schema.oneOf) do | 97 for _, sub in ipairs(schema.oneOf) do |
86 if validate(sub, data) then | 98 if validate(sub, data, root) then |
87 valid = valid + 1 | 99 valid = valid + 1 |
88 end | 100 end |
89 end | 101 end |
90 return valid == 1 | 102 return valid == 1 |
91 end | 103 end |
92 | 104 |
93 if schema.anyOf then | 105 if schema.anyOf then |
94 for _, sub in ipairs(schema.anyOf) do | 106 for _, sub in ipairs(schema.anyOf) do |
95 if validate(sub, data) then | 107 if validate(sub, data, root) then |
96 return true | 108 return true |
97 end | 109 end |
98 end | 110 end |
99 return false | 111 return false |
100 end | 112 end |
101 | 113 |
102 if schema["not"] then | 114 if schema["not"] then |
103 if validate(schema["not"], data) then | 115 if validate(schema["not"], data, root) then |
104 return false | 116 return false |
105 end | 117 end |
106 end | 118 end |
107 | 119 |
108 if schema["if"] then | 120 if schema["if"] then |
109 if validate(schema["if"], data) then | 121 if validate(schema["if"], data, root) then |
110 if schema["then"] then | 122 if schema["then"] then |
111 return validate(schema["then"], data) | 123 return validate(schema["then"], data, root) |
112 end | 124 end |
113 else | 125 else |
114 if schema["else"] then | 126 if schema["else"] then |
115 return validate(schema["else"], data) | 127 return validate(schema["else"], data, root) |
116 end | 128 end |
117 end | 129 end |
118 end | 130 end |
119 | 131 |
120 if schema.const ~= nil and schema.const ~= data then | 132 if schema.const ~= nil and schema.const ~= data then |
135 return false | 147 return false |
136 end | 148 end |
137 | 149 |
138 local validator = type_validators[schema.type] | 150 local validator = type_validators[schema.type] |
139 if validator then | 151 if validator then |
140 return validator(schema, data) | 152 return validator(schema, data, root) |
141 end | 153 end |
142 end | 154 end |
143 return true | 155 return true |
144 end | 156 end |
145 end | 157 end |
146 | 158 |
147 type_validators.table = function(schema, data) | 159 type_validators.table = function(schema, data, root) |
148 if type(data) == "table" then | 160 if type(data) == "table" then |
149 | 161 |
150 if schema.maxItems and #data > schema.maxItems then | 162 if schema.maxItems and #data > schema.maxItems then |
151 return false | 163 return false |
152 end | 164 end |
164 end | 176 end |
165 | 177 |
166 if schema.properties then | 178 if schema.properties then |
167 local additional = schema.additionalProperties or true | 179 local additional = schema.additionalProperties or true |
168 for k, v in pairs(data) do | 180 for k, v in pairs(data) do |
169 if schema.propertyNames and not validate(schema.propertyNames, k) then | 181 if schema.propertyNames and not validate(schema.propertyNames, k, root) then |
170 return false | 182 return false |
171 end | 183 end |
172 local s = schema.properties[k] or additional | 184 local s = schema.properties[k] or additional |
173 if not validate(s, v) then | 185 if not validate(s, v, root) then |
174 return false | 186 return false |
175 end | 187 end |
176 end | 188 end |
177 elseif schema.additionalProperties then | 189 elseif schema.additionalProperties then |
178 for k, v in pairs(data) do | 190 for k, v in pairs(data) do |
179 if schema.propertyNames and not validate(schema.propertyNames, k) then | 191 if schema.propertyNames and not validate(schema.propertyNames, k, root) then |
180 return false | 192 return false |
181 end | 193 end |
182 if not validate(schema.additionalProperties, v) then | 194 if not validate(schema.additionalProperties, v, root) then |
183 return false | 195 return false |
184 end | 196 end |
185 end | 197 end |
186 end | 198 end |
187 | 199 |
197 end | 209 end |
198 | 210 |
199 local p = 0 | 211 local p = 0 |
200 if schema.prefixItems then | 212 if schema.prefixItems then |
201 for i, s in ipairs(schema.prefixItems) do | 213 for i, s in ipairs(schema.prefixItems) do |
202 if validate(s, data[i]) then | 214 if validate(s, data[i], root) then |
203 p = i | 215 p = i |
204 else | 216 else |
205 return false | 217 return false |
206 end | 218 end |
207 end | 219 end |
208 end | 220 end |
209 | 221 |
210 if schema.items then | 222 if schema.items then |
211 for i = p + 1, #data do | 223 for i = p + 1, #data do |
212 if not validate(schema.items, data[i]) then | 224 if not validate(schema.items, data[i], root) then |
213 return false | 225 return false |
214 end | 226 end |
215 end | 227 end |
216 end | 228 end |
217 | 229 |
218 if schema.contains then | 230 if schema.contains then |
219 local found = false | 231 local found = false |
220 for i = 1, #data do | 232 for i = 1, #data do |
221 if validate(schema.contains, data[i]) then | 233 if validate(schema.contains, data[i], root) then |
222 found = true | 234 found = true |
223 break | 235 break |
224 end | 236 end |
225 end | 237 end |
226 if not found then | 238 if not found then |
231 return true | 243 return true |
232 end | 244 end |
233 return false | 245 return false |
234 end | 246 end |
235 | 247 |
236 type_validators.object = function(schema, data) | 248 type_validators.object = function(schema, data, root) |
237 if type(data) == "table" then | 249 if type(data) == "table" then |
238 for k in pairs(data) do | 250 for k in pairs(data) do |
239 if not (type(k) == "string") then | 251 if not (type(k) == "string") then |
240 return false | 252 return false |
241 end | 253 end |
242 end | 254 end |
243 | 255 |
244 return type_validators.table(schema, data) | 256 return type_validators.table(schema, data, root) |
245 end | 257 end |
246 return false | 258 return false |
247 end | 259 end |
248 | 260 |
249 type_validators.array = function(schema, data) | 261 type_validators.array = function(schema, data, root) |
250 if type(data) == "table" then | 262 if type(data) == "table" then |
251 | 263 |
252 for i in pairs(data) do | 264 for i in pairs(data) do |
253 if not (type(i) == "number") then | 265 if not (type(i) == "number") then |
254 return false | 266 return false |
255 end | 267 end |
256 end | 268 end |
257 | 269 |
258 return type_validators.table(schema, data) | 270 return type_validators.table(schema, data, root) |
259 end | 271 end |
260 return false | 272 return false |
261 end | 273 end |
262 | 274 |
263 json_schema_object.validate = validate; | 275 json_schema_object.validate = validate; |