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; |