From e3506253f17137d6d4831b4615d74689446da72c Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Mon, 31 Jan 2022 14:20:06 -0500 Subject: [PATCH] Add optional version to --json --- ChangeLog | 5 +++++ include/qpdf/QPDFJob.hh | 2 +- include/qpdf/auto_job_c_main.hh | 2 +- job.sums | 12 ++++++------ job.yml | 6 +++++- libqpdf/QPDFJob.cc | 4 ++-- libqpdf/QPDFJob_config.cc | 22 ++++++++++++++++++++-- libqpdf/qpdf/auto_job_help.hh | 7 +++++-- libqpdf/qpdf/auto_job_init.hh | 3 ++- libqpdf/qpdf/auto_job_json_init.hh | 3 ++- manual/cli.rst | 12 +++++++++--- qpdf/qtest/qpdf.test | 4 ++-- 12 files changed, 60 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 41f94467..39c96f44 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2022-01-31 Jay Berkenbilt + + * Allow optional version number or "latest" as parameter to + --json, allowing for future specification of json version. + 2022-01-28 Jay Berkenbilt * Add QPDFUsage exception, which is thrown by JSONHandler, diff --git a/include/qpdf/QPDFJob.hh b/include/qpdf/QPDFJob.hh index bedf808e..5a8c88cc 100644 --- a/include/qpdf/QPDFJob.hh +++ b/include/qpdf/QPDFJob.hh @@ -595,7 +595,7 @@ class QPDFJob std::list attachments_to_remove; std::list attachments_to_add; std::list attachments_to_copy; - bool json; + int json_version; std::set json_keys; std::set json_objects; bool check; diff --git a/include/qpdf/auto_job_c_main.hh b/include/qpdf/auto_job_c_main.hh index 3ebc8c7e..42572a3d 100644 --- a/include/qpdf/auto_job_c_main.hh +++ b/include/qpdf/auto_job_c_main.hh @@ -15,7 +15,6 @@ QPDF_DLL Config* flattenRotation(); QPDF_DLL Config* generateAppearances(); QPDF_DLL Config* ignoreXrefStreams(); QPDF_DLL Config* isEncrypted(); -QPDF_DLL Config* json(); QPDF_DLL Config* keepInlineImages(); QPDF_DLL Config* linearize(); QPDF_DLL Config* listAttachments(); @@ -76,3 +75,4 @@ QPDF_DLL Config* objectStreams(char const* parameter); QPDF_DLL Config* passwordMode(char const* parameter); QPDF_DLL Config* removeUnreferencedResources(char const* parameter); QPDF_DLL Config* streamData(char const* parameter); +QPDF_DLL Config* json(char const* parameter); diff --git a/job.sums b/job.sums index 5da66085..0360a53d 100644 --- a/job.sums +++ b/job.sums @@ -3,15 +3,15 @@ generate_auto_job ef1b438aeebed7ca0afcbe4d1f9c54d3acf899aec8410ebc69cd15ec673dd1 include/qpdf/auto_job_c_att.hh 7ad43bb374c1370ef32ebdcdcb7b73a61d281f7f4e3f12755585872ab30fb60e include/qpdf/auto_job_c_copy_att.hh 32275d03cdc69b703dd7e02ba0bbe15756e714e9ad185484773a6178dc09e1ee include/qpdf/auto_job_c_enc.hh 72e138c7b96ed5aacdce78c1dec04b1c20d361faec4f8faf52f64c1d6be99265 -include/qpdf/auto_job_c_main.hh 516adb23cc7e44e614e436880be870d0574e4ebbc706cd855a1360000eed31bb +include/qpdf/auto_job_c_main.hh ff776dd643279330fbf59770d1abf5aaeb13f20bfc5f6a25997aaa72a0907b44 include/qpdf/auto_job_c_pages.hh 931840b329a36ca0e41401190e04537b47f2867671a6643bfd8da74014202671 include/qpdf/auto_job_c_uo.hh 0585b7de459fa479d9e51a45fa92de0ff6dee748efc9ec1cedd0dde6cee1ad50 -job.yml 498459e6c2b7a9bc13168cd58fed75dbd24394fc187230ff7179a22288fa0de5 +job.yml c3e714b3c3e2fc85390d983302ff398aa0992c621e85dbcaee20173b1bd3cb0b libqpdf/qpdf/auto_job_decl.hh 9f79396ec459f191be4c5fe34cf88c265cf47355a1a945fa39169d1c94cf04f6 -libqpdf/qpdf/auto_job_help.hh 23c79f1d2c02bda28f64aace17f69487205c797e7ae2234892cbbabab49d6d47 -libqpdf/qpdf/auto_job_init.hh 8e9e31b6099a662497339b27f6e2d7f779f35011e88a834bee8811c33405a0fe +libqpdf/qpdf/auto_job_help.hh a0ab6ab4dde2ad3d3f17ecae3ea274919119329e075061f3a3973535f5e367de +libqpdf/qpdf/auto_job_init.hh c244e03e8b83ed7db732920f40aff0134e5f2e78a6edb9473ea4dd1934a8953e libqpdf/qpdf/auto_job_json_decl.hh 741a44106f7850b6cbc8af264b5b77bb605475c8d8dd8cd87011d5debbee6269 -libqpdf/qpdf/auto_job_json_init.hh 886dd8ed7ae7691eaa97a0e5b3f1445f4cccab88ed372f530a8524d198c8f1d9 +libqpdf/qpdf/auto_job_json_init.hh 63bbe1c3d673cd56196ec42ec7ede7b531563667d83564aa6680634fcb2cf259 libqpdf/qpdf/auto_job_schema.hh a764050cc99f1cc95645fd1ea2f020c4b778957abc64fbc55c12eac3a369dc92 manual/_ext/qpdf.py e9ac9d6c70642a3d29281ee5ad92ae2422dee8be9306fb8a0bc9dba0ed5e28f3 -manual/cli.rst 79140e023faa0cb77afe0b1dc512dd120ee5617f4db82f842596e4f239f93882 +manual/cli.rst a75a7e34aa9aba4f06e9c88cae9a2d9a2aa4e55a08521dde1478e8f2d80aadab diff --git a/job.yml b/job.yml index bfd4f6f1..4b1df7cf 100644 --- a/job.yml +++ b/job.yml @@ -29,6 +29,9 @@ choices: - all - print - screen + json_version: + - 1 + - latest json_key: # The list of selectable top-level keys id duplicated in the # following places: job.yml, QPDFJob::json_schema, and @@ -88,7 +91,6 @@ options: - generate-appearances - ignore-xref-streams - is-encrypted - - json - keep-inline-images - linearize - list-attachments @@ -156,6 +158,8 @@ options: password-mode: password_mode remove-unreferenced-resources: remove_unref stream-data: stream_data + optional_choices: + json: json_version - table: pages config: c_pages prefix: Pages diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc index 6a26d546..1c6a16d6 100644 --- a/libqpdf/QPDFJob.cc +++ b/libqpdf/QPDFJob.cc @@ -420,7 +420,7 @@ QPDFJob::Members::Members() : collate(0), flatten_rotation(false), list_attachments(false), - json(false), + json_version(0), check(false), optimize_images(false), externalize_inline_images(false), @@ -1924,7 +1924,7 @@ QPDFJob::doInspection(QPDF& pdf) { doCheck(pdf); } - if (m->json) + if (m->json_version) { doJSON(pdf); } diff --git a/libqpdf/QPDFJob_config.cc b/libqpdf/QPDFJob_config.cc index b211b81c..2066e608 100644 --- a/libqpdf/QPDFJob_config.cc +++ b/libqpdf/QPDFJob_config.cc @@ -235,9 +235,27 @@ QPDFJob::Config::isEncrypted() } QPDFJob::Config* -QPDFJob::Config::json() +QPDFJob::Config::json(char const* parameter) { - o.m->json = true; + if (parameter) + { + if (strcmp(parameter, "latest") == 0) + { + o.m->json_version = 1; + } + else + { + o.m->json_version = QUtil::string_to_int(parameter); + } + } + else + { + o.m->json_version = 1; + } + if (o.m->json_version != 1) + { + usage(std::string("unsupported json version ") + parameter); + } o.m->require_outfile = false; return this; } diff --git a/libqpdf/qpdf/auto_job_help.hh b/libqpdf/qpdf/auto_job_help.hh index 18ce5a2b..ff497289 100644 --- a/libqpdf/qpdf/auto_job_help.hh +++ b/libqpdf/qpdf/auto_job_help.hh @@ -788,8 +788,11 @@ output as binary data. Get the key with --list-attachments. ap.addHelpTopic("json", "JSON output for PDF information", R"(Show information about the PDF file in JSON format. Please see the JSON chapter in the qpdf manual for details. )"); -ap.addOptionHelp("--json", "json", "show file in json format", R"(Generate a JSON representation of the file. This is described in -depth in the JSON section of the manual. +ap.addOptionHelp("--json", "json", "show file in json format", R"(--json[=version] + +Generate a JSON representation of the file. This is described in +depth in the JSON section of the manual. "version" may be a +specific version or "latest". )"); ap.addOptionHelp("--json-help", "json", "show format of json output", R"(Describe the format of the JSON output. )"); diff --git a/libqpdf/qpdf/auto_job_init.hh b/libqpdf/qpdf/auto_job_init.hh index 79fdc6d3..28c47be4 100644 --- a/libqpdf/qpdf/auto_job_init.hh +++ b/libqpdf/qpdf/auto_job_init.hh @@ -17,6 +17,7 @@ static char const* decode_level_choices[] = {"none", "generalized", "specialized static char const* object_streams_choices[] = {"disable", "preserve", "generate", 0}; static char const* remove_unref_choices[] = {"auto", "yes", "no", 0}; static char const* flatten_choices[] = {"all", "print", "screen", 0}; +static char const* json_version_choices[] = {"1", "latest", 0}; static char const* json_key_choices[] = {"acroform", "attachments", "encrypt", "objectinfo", "objects", "outlines", "pagelabels", "pages", 0}; static char const* print128_choices[] = {"full", "low", "none", 0}; static char const* modify128_choices[] = {"all", "annotate", "form", "assembly", "none", 0}; @@ -45,7 +46,6 @@ this->ap.addBare("flatten-rotation", [this](){c_main->flattenRotation();}); this->ap.addBare("generate-appearances", [this](){c_main->generateAppearances();}); this->ap.addBare("ignore-xref-streams", [this](){c_main->ignoreXrefStreams();}); this->ap.addBare("is-encrypted", [this](){c_main->isEncrypted();}); -this->ap.addBare("json", [this](){c_main->json();}); this->ap.addBare("keep-inline-images", [this](){c_main->keepInlineImages();}); this->ap.addBare("linearize", [this](){c_main->linearize();}); this->ap.addBare("list-attachments", [this](){c_main->listAttachments();}); @@ -110,6 +110,7 @@ this->ap.addChoices("object-streams", [this](char *x){c_main->objectStreams(x);} this->ap.addChoices("password-mode", [this](char *x){c_main->passwordMode(x);}, true, password_mode_choices); this->ap.addChoices("remove-unreferenced-resources", [this](char *x){c_main->removeUnreferencedResources(x);}, true, remove_unref_choices); this->ap.addChoices("stream-data", [this](char *x){c_main->streamData(x);}, true, stream_data_choices); +this->ap.addChoices("json", [this](char *x){c_main->json(x);}, false, json_version_choices); this->ap.registerOptionTable("pages", b(&ArgParser::argEndPages)); this->ap.addPositional(p(&ArgParser::argPagesPositional)); this->ap.addRequiredParameter("password", p(&ArgParser::argPagesPassword), "password"); diff --git a/libqpdf/qpdf/auto_job_json_init.hh b/libqpdf/qpdf/auto_job_json_init.hh index 39eb6437..df55d328 100644 --- a/libqpdf/qpdf/auto_job_json_init.hh +++ b/libqpdf/qpdf/auto_job_json_init.hh @@ -10,6 +10,7 @@ static char const* decode_level_choices[] = {"none", "generalized", "specialized static char const* object_streams_choices[] = {"disable", "preserve", "generate", 0}; static char const* remove_unref_choices[] = {"auto", "yes", "no", 0}; static char const* flatten_choices[] = {"all", "print", "screen", 0}; +static char const* json_version_choices[] = {"1", "latest", 0}; static char const* json_key_choices[] = {"acroform", "attachments", "encrypt", "objectinfo", "objects", "outlines", "pagelabels", "pages", 0}; static char const* print128_choices[] = {"full", "low", "none", 0}; static char const* modify128_choices[] = {"all", "annotate", "form", "assembly", "none", 0}; @@ -248,7 +249,7 @@ pushKey("showAttachment"); addParameter([this](char const* p) { c_main->showAttachment(p); }); popHandler(); // key: showAttachment pushKey("json"); -addBare([this]() { c_main->json(); }); +addChoices(json_version_choices, [this](char const* p) { c_main->json(p); }); popHandler(); // key: json pushKey("jsonKey"); beginArray(bindJSON(&Handlers::beginInspectJsonKeyArray), bindBare(&Handlers::endInspectJsonKeyArray)); // .inspect.jsonKey[] diff --git a/manual/cli.rst b/manual/cli.rst index dbd64aad..141f8f2a 100644 --- a/manual/cli.rst +++ b/manual/cli.rst @@ -3136,15 +3136,21 @@ See :ref:`json` for details about the qpdf JSON format. Related Options ~~~~~~~~~~~~~~~ -.. qpdf:option:: --json +.. qpdf:option:: --json[=version] .. help: show file in json format Generate a JSON representation of the file. This is described in - depth in the JSON section of the manual. + depth in the JSON section of the manual. "version" may be a + specific version or "latest". Generate a JSON representation of the file. This is described in - depth in :ref:`json`. + depth in :ref:`json`. The version parameter can be used to specify + which json version should be output. The only supported value is + ``1``, but it's possible that a new json output version will be + added in a future version. You can also specify ``latest`` to use + the latest json version. For backward compatibility, the default + value is ``1``. .. qpdf:option:: --json-help diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index 447aa258..f847cee8 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -617,7 +617,7 @@ $td->runtest("list attachments verbose", {$td->FILE => "test76-list-verbose.out", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); $td->runtest("attachments json", - {$td->COMMAND => "qpdf --json --json-key=attachments a.pdf"}, + {$td->COMMAND => "qpdf --json=1 --json-key=attachments a.pdf"}, {$td->FILE => "test76-json.out", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); $td->runtest("remove attachment (test_driver)", @@ -2705,7 +2705,7 @@ $td->runtest("show direct pages", foreach my $f (qw(page_api_2 direct-pages)) { $td->runtest("json for $f", - {$td->COMMAND => "qpdf --json $f.pdf"}, + {$td->COMMAND => "qpdf --json=latest $f.pdf"}, {$td->FILE => "$f-json.out", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); }