From 70e34ff5df254480fffbfa4a9e4d09083d4c7d76 Mon Sep 17 00:00:00 2001 From: spacewander Date: Mon, 17 Aug 2020 15:22:43 +0800 Subject: [PATCH] feat: support $ref without full URI --- lib/jsonschema/store.lua | 12 +++++++++++- t/draft7.lua | 13 +++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/jsonschema/store.lua b/lib/jsonschema/store.lua index 4c12dae..316aaec 100644 --- a/lib/jsonschema/store.lua +++ b/lib/jsonschema/store.lua @@ -36,7 +36,7 @@ local function urlunescape(fragment) return fragment:gsub('%%(%x%x)', percent_unescape):gsub('~[01]', tilde_unescape) end --- attempt to translate a URI fragemnt part to a valid table index: +-- attempt to translate a URI fragment part to a valid table index: -- * if the part can be converted to number, that number+1 is returned to -- compensate with Lua 1-based indices -- * otherwise, the part is returned URL-escaped @@ -192,6 +192,16 @@ function store_mt:insert(schema) local map = {} local function walk(s, p) + -- handle '$id' keyword + if s['$id'] then + local u = url.parse(s['$id']) + if u.schema ~= nil or u.fragment == nil then + error("Only location independent id is supported. Unsupported $id: " .. s['$id']) + end + + map[u.fragment] = self:ref(s).schema + end + local id = s.id if id and s ~= schema and is_schema(p) then -- there is an id, but it is not over: we have 2 different cases (!) diff --git a/t/draft7.lua b/t/draft7.lua index b0d58f9..fafbff8 100644 --- a/t/draft7.lua +++ b/t/draft7.lua @@ -35,6 +35,11 @@ local blacklist = { ['contains keyword validation'] = { ['not array is valid'] = true }, + -- not support: an external resolver is required + ['remote ref, containing refs itself'] = true, + ['Recursive references between schemas'] = true, + ['Location-independent identifier with absolute URI'] = true, + ['Location-independent identifier with base URI change in subschema'] = true, } local supported = { @@ -88,9 +93,10 @@ local supported = { 'spec/JSON-Schema-Test-Suite/tests/draft7/const.json', 'spec/JSON-Schema-Test-Suite/tests/draft7/contains.json', + -- ref + 'spec/JSON-Schema-Test-Suite/tests/draft7/ref.json', -- not support: an external resolver is required -- 'spec/JSON-Schema-Test-Suite/tests/draft7/refRemote.json', - -- 'spec/JSON-Schema-Test-Suite/tests/draft7/ref.json', -- 'spec/JSON-Schema-Test-Suite/tests/draft7/definitions.json', -- not support: todo @@ -114,9 +120,12 @@ for _, descriptor in ipairs(supported) do for _, suite in decode_descriptor(descriptor) do local skipped = blacklist[suite.description] or {} if skipped ~= true then - local validator = jsonschema.generate_validator(suite.schema, { + local ok, validator = pcall(jsonschema.generate_validator, suite.schema, { name = suite.description, }) + if not ok then + error("failed to generate validator for case " .. suite.description .. ", err: " .. validator) + end for _, case in ipairs(suite.tests) do if skipped[case.description] then print("skip suite case: [" .. suite.description .. "] -> [" .. case.description .. "]")