diff options
-rw-r--r-- | libqpdf/JSON.cc | 26 | ||||
-rw-r--r-- | libtests/json.cc | 11 | ||||
-rw-r--r-- | libtests/qtest/json/json.out | 4 | ||||
-rw-r--r-- | manual/qpdf-manual.xml | 17 |
4 files changed, 51 insertions, 7 deletions
diff --git a/libqpdf/JSON.cc b/libqpdf/JSON.cc index 8565a831..247d3c86 100644 --- a/libqpdf/JSON.cc +++ b/libqpdf/JSON.cc @@ -323,6 +323,7 @@ JSON::checkSchemaInternal(JSON_value* this_v, JSON_value* sch_v, err_prefix = "json key \"" + prefix + "\""; } + std::string pattern_key; if (sch_dict) { if (! this_dict) @@ -331,6 +332,31 @@ JSON::checkSchemaInternal(JSON_value* this_v, JSON_value* sch_v, errors.push_back(err_prefix + " is supposed to be a dictionary"); return false; } + auto members = sch_dict->members; + std::string key; + if ((members.size() == 1) && + ((key = members.begin()->first, key.length() > 2) && + (key.at(0) == '<') && + (key.at(key.length() - 1) == '>'))) + { + pattern_key = key; + } + } + + if (sch_dict && (! pattern_key.empty())) + { + auto pattern_schema = sch_dict->members[pattern_key].getPointer(); + for (auto iter: this_dict->members) + { + std::string const& key = iter.first; + checkSchemaInternal( + this_dict->members[key].getPointer(), + pattern_schema, + errors, prefix + "." + key); + } + } + else if (sch_dict) + { for (std::map<std::string, PointerHolder<JSON_value> >::iterator iter = sch_dict->members.begin(); iter != sch_dict->members.end(); ++iter) diff --git a/libtests/json.cc b/libtests/json.cc index e3086c18..1ee7a5d3 100644 --- a/libtests/json.cc +++ b/libtests/json.cc @@ -112,6 +112,11 @@ static void test_schema() " >>" " ]" ">>").getJSON(); + JSON three = JSON::makeDictionary(); + three.addDictionaryMember( + "<objid>", + QPDFObjectHandle::parse("<< /z (ebra) >>").getJSON()); + schema.addDictionaryMember("/three", three); JSON a = QPDFObjectHandle::parse("[(not a) (dictionary)]").getJSON(); check_schema(a, schema, false, "top-level type mismatch"); JSON b = QPDFObjectHandle::parse( @@ -142,8 +147,12 @@ static void test_schema() " /glarp (4 enspliel)" " >>" " ]" + " /three <<" + " /anything << /x (oops) >>" + " /else << /z (okay) >>" + " >>" ">>").getJSON(); - check_schema(b, schema, false, "top-level type mismatch"); + check_schema(b, schema, false, "missing items"); check_schema(a, a, false, "top-level schema array error"); check_schema(b, b, false, "lower-level schema array error"); check_schema(schema, schema, true, "pass"); diff --git a/libtests/qtest/json/json.out b/libtests/qtest/json/json.out index f06cc1fb..ad668e51 100644 --- a/libtests/qtest/json/json.out +++ b/libtests/qtest/json/json.out @@ -1,11 +1,13 @@ --- top-level type mismatch top-level object is supposed to be a dictionary --- ---- top-level type mismatch +--- missing items json key "./one./a": key "/q" is present in schema but missing in object json key "./one./a./r" is supposed to be a dictionary json key "./one./a./s" is supposed to be an array json key "./one./a": key "/t" is not present in schema but appears in object +json key "./three./anything": key "/z" is present in schema but missing in object +json key "./three./anything": key "/x" is not present in schema but appears in object json key "./two.1": key "/glarp" is present in schema but missing in object json key "./two.1": key "/flarp" is not present in schema but appears in object json key "./two.2" is supposed to be a dictionary diff --git a/manual/qpdf-manual.xml b/manual/qpdf-manual.xml index 83cb6bf9..a2dff114 100644 --- a/manual/qpdf-manual.xml +++ b/manual/qpdf-manual.xml @@ -3082,11 +3082,18 @@ outfile.pdf</option> <itemizedlist> <listitem> <para> - A dictionary in the help output means that the corresponding - location in the actual JSON output is also a dictionary with - exactly the same keys; that is, no keys present in help are - absent in the real output, and no keys will be present in - the real output that are not in help. + A dictionary in the help output means that the + corresponding location in the actual JSON output is also a + dictionary with exactly the same keys; that is, no keys + present in help are absent in the real output, and no keys + will be present in the real output that are not in help. As + a special case, if the dictionary has a single key whose + name starts with <literal><</literal> and ends with + <literal>></literal>, it means that the JSON output is a + dictionary that can have any keys, each of which conforms + to the value of the special key. This is used for cases in + which the keys of the dictionary are things like object + IDs. </para> </listitem> <listitem> |