aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf
diff options
context:
space:
mode:
Diffstat (limited to 'libqpdf')
-rw-r--r--libqpdf/QPDFJob_json.cc170
-rw-r--r--libqpdf/qpdf/auto_job_json_decl.hh38
-rw-r--r--libqpdf/qpdf/auto_job_json_init.hh582
-rw-r--r--libqpdf/qpdf/auto_job_schema.hh4
4 files changed, 538 insertions, 256 deletions
diff --git a/libqpdf/QPDFJob_json.cc b/libqpdf/QPDFJob_json.cc
index 368b2a0a..967f0cc9 100644
--- a/libqpdf/QPDFJob_json.cc
+++ b/libqpdf/QPDFJob_json.cc
@@ -27,24 +27,20 @@ namespace
typedef std::function<void()> bare_handler_t;
typedef std::function<void(char const*)> param_handler_t;
typedef std::function<void(JSON)> json_handler_t;
- typedef std::function<void(std::string const& key)> setup_handler_t;
-
- void addBare(std::string const& key, bare_handler_t);
- void addParameter(std::string const& key, param_handler_t);
- void addChoices(std::string const& key, char const** choices,
- param_handler_t);
- void doSetup(std::string const& key, setup_handler_t);
- void beginDict(std::string const& key,
- json_handler_t start_fn,
+
+ void addBare(bare_handler_t);
+ void addParameter(param_handler_t);
+ void addChoices(char const** choices, param_handler_t);
+ void pushKey(std::string const& key);
+ void beginDict(json_handler_t start_fn,
bare_handler_t end_fn);
- void beginArray(std::string const& key,
- json_handler_t start_fn,
+ void beginArray(json_handler_t start_fn,
bare_handler_t end_fn);
- void endContainer();
+ void ignoreItem();
+ void popHandler();
bare_handler_t bindBare(void (Handlers::*f)());
json_handler_t bindJSON(void (Handlers::*f)(JSON));
- setup_handler_t bindSetup(void (Handlers::*f)(std::string const&));
std::list<std::shared_ptr<JSONHandler>> json_handlers;
bool partial;
@@ -84,12 +80,6 @@ Handlers::bindJSON(void (Handlers::*f)(JSON))
return std::bind(std::mem_fn(f), this, std::placeholders::_1);
}
-Handlers::setup_handler_t
-Handlers::bindSetup(void (Handlers::*f)(std::string const&))
-{
- return std::bind(std::mem_fn(f), this, std::placeholders::_1);
-}
-
void
Handlers::initHandlers()
{
@@ -113,10 +103,9 @@ Handlers::initHandlers()
}
void
-Handlers::addBare(std::string const& key, bare_handler_t fn)
+Handlers::addBare(bare_handler_t fn)
{
- auto h = std::make_shared<JSONHandler>();
- h->addBoolHandler([this, fn](std::string const& path, bool v){
+ jh->addBoolHandler([this, fn](std::string const& path, bool v){
if (! v)
{
usage(path + ": value must be true");
@@ -126,26 +115,22 @@ Handlers::addBare(std::string const& key, bare_handler_t fn)
fn();
}
});
- jh->addDictKeyHandler(key, h);
}
void
-Handlers::addParameter(std::string const& key, param_handler_t fn)
+Handlers::addParameter(param_handler_t fn)
{
- auto h = std::make_shared<JSONHandler>();
- h->addStringHandler(
+ jh->addStringHandler(
[fn](std::string const& path, std::string const& parameter){
fn(parameter.c_str());
});
- jh->addDictKeyHandler(key, h);
}
void
-Handlers::addChoices(std::string const& key, char const** choices,
+Handlers::addChoices(char const** choices,
param_handler_t fn)
{
- auto h = std::make_shared<JSONHandler>();
- h->addStringHandler(
+ jh->addStringHandler(
[fn, choices, this](
std::string const& path, std::string const& parameter){
@@ -180,47 +165,45 @@ Handlers::addChoices(std::string const& key, char const** choices,
}
fn(parameter.c_str());
});
- jh->addDictKeyHandler(key, h);
}
void
-Handlers::doSetup(std::string const& key, setup_handler_t fn)
+Handlers::pushKey(std::string const& key)
{
- fn(key);
+ auto new_jh = std::make_shared<JSONHandler>();
+ this->jh->addDictKeyHandler(key, new_jh);
+ this->json_handlers.push_back(new_jh);
+ this->jh = new_jh.get();
}
void
-Handlers::beginDict(std::string const& key,
- json_handler_t start_fn,
- bare_handler_t end_fn)
+Handlers::beginDict(json_handler_t start_fn, bare_handler_t end_fn)
{
- auto new_jh = std::make_shared<JSONHandler>();
- new_jh->addDictHandlers(
+ jh->addDictHandlers(
[start_fn](std::string const&, JSON j){ start_fn(j); },
[end_fn](std::string const&){ end_fn(); });
- this->jh->addDictKeyHandler(key, new_jh);
- this->json_handlers.push_back(new_jh);
- this->jh = new_jh.get();
}
void
-Handlers::beginArray(std::string const& key,
- json_handler_t start_fn,
- bare_handler_t end_fn)
+Handlers::beginArray(json_handler_t start_fn, bare_handler_t end_fn)
{
- auto new_jh = std::make_shared<JSONHandler>();
auto item_jh = std::make_shared<JSONHandler>();
- new_jh->addArrayHandlers(
+ jh->addArrayHandlers(
[start_fn](std::string const&, JSON j){ start_fn(j); },
[end_fn](std::string const&){ end_fn(); },
item_jh);
- this->jh->addDictKeyHandler(key, new_jh);
this->json_handlers.push_back(item_jh);
this->jh = item_jh.get();
}
void
-Handlers::endContainer()
+Handlers::ignoreItem()
+{
+ jh->addAnyHandler([](std::string const&, JSON){});
+}
+
+void
+Handlers::popHandler()
{
this->json_handlers.pop_back();
this->jh = this->json_handlers.back().get();
@@ -245,25 +228,25 @@ Handlers::endInput()
}
void
-Handlers::setupInputFilename(std::string const& key)
+Handlers::setupInputFilename()
{
- addParameter(key, [this](char const* p) {
+ addParameter([this](char const* p) {
c_main->inputFile(p);
});
}
void
-Handlers::setupInputPassword(std::string const& key)
+Handlers::setupInputPassword()
{
- addParameter(key, [this](char const* p) {
+ addParameter([this](char const* p) {
c_main->password(p);
});
}
void
-Handlers::setupInputEmpty(std::string const& key)
+Handlers::setupInputEmpty()
{
- addBare(key, [this]() {
+ addBare([this]() {
c_main->emptyInput();
});
}
@@ -281,17 +264,17 @@ Handlers::endOutput()
}
void
-Handlers::setupOutputFilename(std::string const& key)
+Handlers::setupOutputFilename()
{
- addParameter(key, [this](char const* p) {
+ addParameter([this](char const* p) {
c_main->outputFile(p);
});
}
void
-Handlers::setupOutputReplaceInput(std::string const& key)
+Handlers::setupOutputReplaceInput()
{
- addBare(key, [this]() {
+ addBare([this]() {
c_main->replaceInput();
});
}
@@ -359,15 +342,17 @@ Handlers::endOutputOptionsEncrypt()
}
void
-Handlers::setupOutputOptionsEncryptUserPassword(std::string const& key)
+Handlers::setupOutputOptionsEncryptUserPassword()
{
- // Key handled in beginOutputOptionsEncrypt
+ // handled in beginOutputOptionsEncrypt
+ ignoreItem();
}
void
-Handlers::setupOutputOptionsEncryptOwnerPassword(std::string const& key)
+Handlers::setupOutputOptionsEncryptOwnerPassword()
{
- // Key handled in beginOutputOptionsEncrypt
+ // handled in beginOutputOptionsEncrypt
+ ignoreItem();
}
void
@@ -431,6 +416,30 @@ Handlers::endInspect()
}
void
+Handlers::beginInspectJsonKeyArray(JSON)
+{
+ // nothing needed
+}
+
+void
+Handlers::endInspectJsonKeyArray()
+{
+ // nothing needed
+}
+
+void
+Handlers::beginInspectJsonObjectArray(JSON)
+{
+ // nothing needed
+}
+
+void
+Handlers::endInspectJsonObjectArray()
+{
+ // nothing needed
+}
+
+void
Handlers::beginOptionsAddAttachmentArray(JSON)
{
// nothing needed
@@ -456,9 +465,9 @@ Handlers::endOptionsAddAttachment()
}
void
-Handlers::setupOptionsAddAttachmentPath(std::string const& key)
+Handlers::setupOptionsAddAttachmentPath()
{
- addParameter(key, [this](char const* p) {
+ addParameter([this](char const* p) {
c_att->path(p);
});
}
@@ -489,17 +498,17 @@ Handlers::endOptionsCopyAttachmentsFrom()
}
void
-Handlers::setupOptionsCopyAttachmentsFromPath(std::string const& key)
+Handlers::setupOptionsCopyAttachmentsFromPath()
{
- addParameter(key, [this](char const* p) {
+ addParameter([this](char const* p) {
c_copy_att->path(p);
});
}
void
-Handlers::setupOptionsCopyAttachmentsFromPassword(std::string const& key)
+Handlers::setupOptionsCopyAttachmentsFromPassword()
{
- addParameter(key, [this](char const* p) {
+ addParameter([this](char const* p) {
c_copy_att->password(p);
});
}
@@ -554,21 +563,24 @@ Handlers::endOptionsPages()
}
void
-Handlers::setupOptionsPagesFile(std::string const& key)
+Handlers::setupOptionsPagesFile()
{
// handled in beginOptionsPages
+ ignoreItem();
}
void
-Handlers::setupOptionsPagesPassword(std::string const& key)
+Handlers::setupOptionsPagesPassword()
{
// handled in beginOptionsPages
+ ignoreItem();
}
void
-Handlers::setupOptionsPagesRange(std::string const& key)
+Handlers::setupOptionsPagesRange()
{
// handled in beginOptionsPages
+ ignoreItem();
}
void
@@ -585,17 +597,17 @@ Handlers::endOptionsOverlay()
}
void
-Handlers::setupOptionsOverlayFile(std::string const& key)
+Handlers::setupOptionsOverlayFile()
{
- addParameter(key, [this](char const* p) {
+ addParameter([this](char const* p) {
c_uo->path(p);
});
}
void
-Handlers::setupOptionsOverlayPassword(std::string const& key)
+Handlers::setupOptionsOverlayPassword()
{
- addParameter(key, [this](char const* p) {
+ addParameter([this](char const* p) {
c_uo->password(p);
});
}
@@ -614,17 +626,17 @@ Handlers::endOptionsUnderlay()
}
void
-Handlers::setupOptionsUnderlayFile(std::string const& key)
+Handlers::setupOptionsUnderlayFile()
{
- addParameter(key, [this](char const* p) {
+ addParameter([this](char const* p) {
c_uo->path(p);
});
}
void
-Handlers::setupOptionsUnderlayPassword(std::string const& key)
+Handlers::setupOptionsUnderlayPassword()
{
- addParameter(key, [this](char const* p) {
+ addParameter([this](char const* p) {
c_uo->password(p);
});
}
diff --git a/libqpdf/qpdf/auto_job_json_decl.hh b/libqpdf/qpdf/auto_job_json_decl.hh
index aa9b8137..8dc37adf 100644
--- a/libqpdf/qpdf/auto_job_json_decl.hh
+++ b/libqpdf/qpdf/auto_job_json_decl.hh
@@ -5,19 +5,19 @@
//
void beginInput(JSON);
void endInput();
-void setupInputFilename(std::string const&);
-void setupInputPassword(std::string const&);
-void setupInputEmpty(std::string const&);
+void setupInputFilename();
+void setupInputPassword();
+void setupInputEmpty();
void beginOutput(JSON);
void endOutput();
-void setupOutputFilename(std::string const&);
-void setupOutputReplaceInput(std::string const&);
+void setupOutputFilename();
+void setupOutputReplaceInput();
void beginOutputOptions(JSON);
void endOutputOptions();
void beginOutputOptionsEncrypt(JSON);
void endOutputOptionsEncrypt();
-void setupOutputOptionsEncryptUserPassword(std::string const&);
-void setupOutputOptionsEncryptOwnerPassword(std::string const&);
+void setupOutputOptionsEncryptUserPassword();
+void setupOutputOptionsEncryptOwnerPassword();
void beginOutputOptionsEncrypt40bit(JSON);
void endOutputOptionsEncrypt40bit();
void beginOutputOptionsEncrypt128bit(JSON);
@@ -26,31 +26,35 @@ void beginOutputOptionsEncrypt256bit(JSON);
void endOutputOptionsEncrypt256bit();
void beginInspect(JSON);
void endInspect();
+void beginInspectJsonKeyArray(JSON);
+void endInspectJsonKeyArray();
+void beginInspectJsonObjectArray(JSON);
+void endInspectJsonObjectArray();
void beginOptions(JSON);
void endOptions();
void beginOptionsAddAttachmentArray(JSON);
void endOptionsAddAttachmentArray();
void beginOptionsAddAttachment(JSON);
void endOptionsAddAttachment();
-void setupOptionsAddAttachmentPath(std::string const&);
+void setupOptionsAddAttachmentPath();
void beginOptionsCopyAttachmentsFromArray(JSON);
void endOptionsCopyAttachmentsFromArray();
void beginOptionsCopyAttachmentsFrom(JSON);
void endOptionsCopyAttachmentsFrom();
-void setupOptionsCopyAttachmentsFromPath(std::string const&);
-void setupOptionsCopyAttachmentsFromPassword(std::string const&);
+void setupOptionsCopyAttachmentsFromPath();
+void setupOptionsCopyAttachmentsFromPassword();
void beginOptionsPagesArray(JSON);
void endOptionsPagesArray();
void beginOptionsPages(JSON);
void endOptionsPages();
-void setupOptionsPagesFile(std::string const&);
-void setupOptionsPagesPassword(std::string const&);
-void setupOptionsPagesRange(std::string const&);
+void setupOptionsPagesFile();
+void setupOptionsPagesPassword();
+void setupOptionsPagesRange();
void beginOptionsOverlay(JSON);
void endOptionsOverlay();
-void setupOptionsOverlayFile(std::string const&);
-void setupOptionsOverlayPassword(std::string const&);
+void setupOptionsOverlayFile();
+void setupOptionsOverlayPassword();
void beginOptionsUnderlay(JSON);
void endOptionsUnderlay();
-void setupOptionsUnderlayFile(std::string const&);
-void setupOptionsUnderlayPassword(std::string const&);
+void setupOptionsUnderlayFile();
+void setupOptionsUnderlayPassword();
diff --git a/libqpdf/qpdf/auto_job_json_init.hh b/libqpdf/qpdf/auto_job_json_init.hh
index 87489412..3e082b84 100644
--- a/libqpdf/qpdf/auto_job_json_init.hh
+++ b/libqpdf/qpdf/auto_job_json_init.hh
@@ -14,161 +14,427 @@ static char const* json_key_choices[] = {"acroform", "attachments", "encrypt", "
static char const* print128_choices[] = {"full", "low", "none", 0};
static char const* modify128_choices[] = {"all", "annotate", "form", "assembly", "none", 0};
-beginDict("input", bindJSON(&Handlers::beginInput), bindBare(&Handlers::endInput)); // .input
-doSetup("filename", bindSetup(&Handlers::setupInputFilename));
-doSetup("password", bindSetup(&Handlers::setupInputPassword));
-addParameter("passwordFile", [this](char const* p) { c_main->passwordFile(p); });
-doSetup("empty", bindSetup(&Handlers::setupInputEmpty));
-endContainer(); // .input
-beginDict("output", bindJSON(&Handlers::beginOutput), bindBare(&Handlers::endOutput)); // .output
-doSetup("filename", bindSetup(&Handlers::setupOutputFilename));
-doSetup("replaceInput", bindSetup(&Handlers::setupOutputReplaceInput));
-beginDict("options", bindJSON(&Handlers::beginOutputOptions), bindBare(&Handlers::endOutputOptions)); // .output.options
-addBare("qdf", [this]() { c_main->qdf(); });
-addBare("preserveUnreferenced", [this]() { c_main->preserveUnreferenced(); });
-addBare("newlineBeforeEndstream", [this]() { c_main->newlineBeforeEndstream(); });
-addChoices("normalizeContent", yn_choices, [this](char const* p) { c_main->normalizeContent(p); });
-addChoices("streamData", stream_data_choices, [this](char const* p) { c_main->streamData(p); });
-addChoices("compressStreams", yn_choices, [this](char const* p) { c_main->compressStreams(p); });
-addBare("recompressFlate", [this]() { c_main->recompressFlate(); });
-addChoices("decodeLevel", decode_level_choices, [this](char const* p) { c_main->decodeLevel(p); });
-addBare("decrypt", [this]() { c_main->decrypt(); });
-addBare("staticAesIv", [this]() { c_main->staticAesIv(); });
-addBare("staticId", [this]() { c_main->staticId(); });
-addBare("noOriginalObjectIds", [this]() { c_main->noOriginalObjectIds(); });
-addParameter("copyEncryption", [this](char const* p) { c_main->copyEncryption(p); });
-addParameter("encryptionFilePassword", [this](char const* p) { c_main->encryptionFilePassword(p); });
-addBare("linearize", [this]() { c_main->linearize(); });
-addParameter("linearizePass1", [this](char const* p) { c_main->linearizePass1(p); });
-addChoices("objectStreams", object_streams_choices, [this](char const* p) { c_main->objectStreams(p); });
-addParameter("minVersion", [this](char const* p) { c_main->minVersion(p); });
-addParameter("forceVersion", [this](char const* p) { c_main->forceVersion(p); });
-addBare("progress", [this]() { c_main->progress(); });
-addParameter("splitPages", [this](char const* p) { c_main->splitPages(p); });
-beginDict("encrypt", bindJSON(&Handlers::beginOutputOptionsEncrypt), bindBare(&Handlers::endOutputOptionsEncrypt)); // .output.options.encrypt
-doSetup("userPassword", bindSetup(&Handlers::setupOutputOptionsEncryptUserPassword));
-doSetup("ownerPassword", bindSetup(&Handlers::setupOutputOptionsEncryptOwnerPassword));
-beginDict("40bit", bindJSON(&Handlers::beginOutputOptionsEncrypt40bit), bindBare(&Handlers::endOutputOptionsEncrypt40bit)); // .output.options.encrypt.40bit
-addChoices("annotate", yn_choices, [this](char const* p) { c_enc->annotate(p); });
-addChoices("extract", yn_choices, [this](char const* p) { c_enc->extract(p); });
-addChoices("modify", modify128_choices, [this](char const* p) { c_enc->modify(p); });
-addChoices("print", print128_choices, [this](char const* p) { c_enc->print(p); });
-endContainer(); // .output.options.encrypt.40bit
-beginDict("128bit", bindJSON(&Handlers::beginOutputOptionsEncrypt128bit), bindBare(&Handlers::endOutputOptionsEncrypt128bit)); // .output.options.encrypt.128bit
-addChoices("accessibility", yn_choices, [this](char const* p) { c_enc->accessibility(p); });
-addChoices("annotate", yn_choices, [this](char const* p) { c_enc->annotate(p); });
-addChoices("assemble", yn_choices, [this](char const* p) { c_enc->assemble(p); });
-addBare("cleartextMetadata", [this]() { c_enc->cleartextMetadata(); });
-addChoices("extract", yn_choices, [this](char const* p) { c_enc->extract(p); });
-addChoices("form", yn_choices, [this](char const* p) { c_enc->form(p); });
-addChoices("modifyOther", yn_choices, [this](char const* p) { c_enc->modifyOther(p); });
-addChoices("modify", modify128_choices, [this](char const* p) { c_enc->modify(p); });
-addChoices("print", print128_choices, [this](char const* p) { c_enc->print(p); });
-addBare("forceV4", [this]() { c_enc->forceV4(); });
-addChoices("useAes", yn_choices, [this](char const* p) { c_enc->useAes(p); });
-endContainer(); // .output.options.encrypt.128bit
-beginDict("256bit", bindJSON(&Handlers::beginOutputOptionsEncrypt256bit), bindBare(&Handlers::endOutputOptionsEncrypt256bit)); // .output.options.encrypt.256bit
-addChoices("accessibility", yn_choices, [this](char const* p) { c_enc->accessibility(p); });
-addChoices("annotate", yn_choices, [this](char const* p) { c_enc->annotate(p); });
-addChoices("assemble", yn_choices, [this](char const* p) { c_enc->assemble(p); });
-addBare("cleartextMetadata", [this]() { c_enc->cleartextMetadata(); });
-addChoices("extract", yn_choices, [this](char const* p) { c_enc->extract(p); });
-addChoices("form", yn_choices, [this](char const* p) { c_enc->form(p); });
-addChoices("modifyOther", yn_choices, [this](char const* p) { c_enc->modifyOther(p); });
-addChoices("modify", modify128_choices, [this](char const* p) { c_enc->modify(p); });
-addChoices("print", print128_choices, [this](char const* p) { c_enc->print(p); });
-addBare("allowInsecure", [this]() { c_enc->allowInsecure(); });
-addBare("forceR5", [this]() { c_enc->forceR5(); });
-endContainer(); // .output.options.encrypt.256bit
-endContainer(); // .output.options.encrypt
-endContainer(); // .output.options
-endContainer(); // .output
-beginDict("inspect", bindJSON(&Handlers::beginInspect), bindBare(&Handlers::endInspect)); // .inspect
-addBare("check", [this]() { c_main->check(); });
-addBare("checkLinearization", [this]() { c_main->checkLinearization(); });
-addBare("filteredStreamData", [this]() { c_main->filteredStreamData(); });
-addBare("rawStreamData", [this]() { c_main->rawStreamData(); });
-addBare("showEncryption", [this]() { c_main->showEncryption(); });
-addBare("showEncryptionKey", [this]() { c_main->showEncryptionKey(); });
-addBare("showLinearization", [this]() { c_main->showLinearization(); });
-addBare("showNpages", [this]() { c_main->showNpages(); });
-addParameter("showObject", [this](char const* p) { c_main->showObject(p); });
-addBare("showPages", [this]() { c_main->showPages(); });
-addBare("showXref", [this]() { c_main->showXref(); });
-addBare("withImages", [this]() { c_main->withImages(); });
-addBare("listAttachments", [this]() { c_main->listAttachments(); });
-addParameter("showAttachment", [this](char const* p) { c_main->showAttachment(p); });
-addBare("json", [this]() { c_main->json(); });
-addChoices("jsonKey", json_key_choices, [this](char const* p) { c_main->jsonKey(p); });
-addParameter("jsonObject", [this](char const* p) { c_main->jsonObject(p); });
-endContainer(); // .inspect
-beginDict("options", bindJSON(&Handlers::beginOptions), bindBare(&Handlers::endOptions)); // .options
-addBare("allowWeakCrypto", [this]() { c_main->allowWeakCrypto(); });
-addBare("deterministicId", [this]() { c_main->deterministicId(); });
-addChoices("keepFilesOpen", yn_choices, [this](char const* p) { c_main->keepFilesOpen(p); });
-addParameter("keepFilesOpenThreshold", [this](char const* p) { c_main->keepFilesOpenThreshold(p); });
-addBare("noWarn", [this]() { c_main->noWarn(); });
-addBare("verbose", [this]() { c_main->verbose(); });
-addBare("ignoreXrefStreams", [this]() { c_main->ignoreXrefStreams(); });
-addBare("passwordIsHexKey", [this]() { c_main->passwordIsHexKey(); });
-addChoices("passwordMode", password_mode_choices, [this](char const* p) { c_main->passwordMode(p); });
-addBare("suppressPasswordRecovery", [this]() { c_main->suppressPasswordRecovery(); });
-addBare("suppressRecovery", [this]() { c_main->suppressRecovery(); });
-addBare("coalesceContents", [this]() { c_main->coalesceContents(); });
-addParameter("compressionLevel", [this](char const* p) { c_main->compressionLevel(p); });
-addBare("externalizeInlineImages", [this]() { c_main->externalizeInlineImages(); });
-addParameter("iiMinBytes", [this](char const* p) { c_main->iiMinBytes(p); });
-addChoices("removeUnreferencedResources", remove_unref_choices, [this](char const* p) { c_main->removeUnreferencedResources(p); });
-beginArray("options", bindJSON(&Handlers::beginOptionsAddAttachmentArray), bindBare(&Handlers::endOptionsAddAttachmentArray)); // .options.addAttachment[]
-beginDict("addAttachment", bindJSON(&Handlers::beginOptionsAddAttachment), bindBare(&Handlers::endOptionsAddAttachment)); // .options.addAttachment
-doSetup("path", bindSetup(&Handlers::setupOptionsAddAttachmentPath));
-addParameter("creationdate", [this](char const* p) { c_att->creationdate(p); });
-addParameter("description", [this](char const* p) { c_att->description(p); });
-addParameter("filename", [this](char const* p) { c_att->filename(p); });
-addParameter("key", [this](char const* p) { c_att->key(p); });
-addParameter("mimetype", [this](char const* p) { c_att->mimetype(p); });
-addParameter("moddate", [this](char const* p) { c_att->moddate(p); });
-addBare("replace", [this]() { c_att->replace(); });
-endContainer(); // .options.addAttachment
-endContainer(); // .options.addAttachment[]
-addParameter("removeAttachment", [this](char const* p) { c_main->removeAttachment(p); });
-beginArray("options", bindJSON(&Handlers::beginOptionsCopyAttachmentsFromArray), bindBare(&Handlers::endOptionsCopyAttachmentsFromArray)); // .options.copyAttachmentsFrom[]
-beginDict("copyAttachmentsFrom", bindJSON(&Handlers::beginOptionsCopyAttachmentsFrom), bindBare(&Handlers::endOptionsCopyAttachmentsFrom)); // .options.copyAttachmentsFrom
-doSetup("path", bindSetup(&Handlers::setupOptionsCopyAttachmentsFromPath));
-doSetup("password", bindSetup(&Handlers::setupOptionsCopyAttachmentsFromPassword));
-addParameter("prefix", [this](char const* p) { c_copy_att->prefix(p); });
-endContainer(); // .options.copyAttachmentsFrom
-endContainer(); // .options.copyAttachmentsFrom[]
-addParameter("collate", [this](char const* p) { c_main->collate(p); });
-addChoices("flattenAnnotations", flatten_choices, [this](char const* p) { c_main->flattenAnnotations(p); });
-addBare("flattenRotation", [this]() { c_main->flattenRotation(); });
-addBare("generateAppearances", [this]() { c_main->generateAppearances(); });
-addBare("keepInlineImages", [this]() { c_main->keepInlineImages(); });
-addParameter("oiMinArea", [this](char const* p) { c_main->oiMinArea(p); });
-addParameter("oiMinHeight", [this](char const* p) { c_main->oiMinHeight(p); });
-addParameter("oiMinWidth", [this](char const* p) { c_main->oiMinWidth(p); });
-addBare("optimizeImages", [this]() { c_main->optimizeImages(); });
-beginArray("options", bindJSON(&Handlers::beginOptionsPagesArray), bindBare(&Handlers::endOptionsPagesArray)); // .options.pages[]
-beginDict("pages", bindJSON(&Handlers::beginOptionsPages), bindBare(&Handlers::endOptionsPages)); // .options.pages
-doSetup("file", bindSetup(&Handlers::setupOptionsPagesFile));
-doSetup("password", bindSetup(&Handlers::setupOptionsPagesPassword));
-doSetup("range", bindSetup(&Handlers::setupOptionsPagesRange));
-endContainer(); // .options.pages
-endContainer(); // .options.pages[]
-addBare("removePageLabels", [this]() { c_main->removePageLabels(); });
-addParameter("rotate", [this](char const* p) { c_main->rotate(p); });
-beginDict("overlay", bindJSON(&Handlers::beginOptionsOverlay), bindBare(&Handlers::endOptionsOverlay)); // .options.overlay
-doSetup("file", bindSetup(&Handlers::setupOptionsOverlayFile));
-doSetup("password", bindSetup(&Handlers::setupOptionsOverlayPassword));
-addParameter("from", [this](char const* p) { c_uo->from(p); });
-addParameter("repeat", [this](char const* p) { c_uo->repeat(p); });
-addParameter("to", [this](char const* p) { c_uo->to(p); });
-endContainer(); // .options.overlay
-beginDict("underlay", bindJSON(&Handlers::beginOptionsUnderlay), bindBare(&Handlers::endOptionsUnderlay)); // .options.underlay
-doSetup("file", bindSetup(&Handlers::setupOptionsUnderlayFile));
-doSetup("password", bindSetup(&Handlers::setupOptionsUnderlayPassword));
-addParameter("from", [this](char const* p) { c_uo->from(p); });
-addParameter("repeat", [this](char const* p) { c_uo->repeat(p); });
-addParameter("to", [this](char const* p) { c_uo->to(p); });
-endContainer(); // .options.underlay
-endContainer(); // .options
+pushKey("input");
+beginDict(bindJSON(&Handlers::beginInput), bindBare(&Handlers::endInput)); // .input
+pushKey("filename");
+setupInputFilename();
+popHandler(); // key: filename
+pushKey("password");
+setupInputPassword();
+popHandler(); // key: password
+pushKey("passwordFile");
+addParameter([this](char const* p) { c_main->passwordFile(p); });
+popHandler(); // key: passwordFile
+pushKey("empty");
+setupInputEmpty();
+popHandler(); // key: empty
+popHandler(); // key: input
+pushKey("output");
+beginDict(bindJSON(&Handlers::beginOutput), bindBare(&Handlers::endOutput)); // .output
+pushKey("filename");
+setupOutputFilename();
+popHandler(); // key: filename
+pushKey("replaceInput");
+setupOutputReplaceInput();
+popHandler(); // key: replaceInput
+pushKey("options");
+beginDict(bindJSON(&Handlers::beginOutputOptions), bindBare(&Handlers::endOutputOptions)); // .output.options
+pushKey("qdf");
+addBare([this]() { c_main->qdf(); });
+popHandler(); // key: qdf
+pushKey("preserveUnreferenced");
+addBare([this]() { c_main->preserveUnreferenced(); });
+popHandler(); // key: preserveUnreferenced
+pushKey("newlineBeforeEndstream");
+addBare([this]() { c_main->newlineBeforeEndstream(); });
+popHandler(); // key: newlineBeforeEndstream
+pushKey("normalizeContent");
+addChoices(yn_choices, [this](char const* p) { c_main->normalizeContent(p); });
+popHandler(); // key: normalizeContent
+pushKey("streamData");
+addChoices(stream_data_choices, [this](char const* p) { c_main->streamData(p); });
+popHandler(); // key: streamData
+pushKey("compressStreams");
+addChoices(yn_choices, [this](char const* p) { c_main->compressStreams(p); });
+popHandler(); // key: compressStreams
+pushKey("recompressFlate");
+addBare([this]() { c_main->recompressFlate(); });
+popHandler(); // key: recompressFlate
+pushKey("decodeLevel");
+addChoices(decode_level_choices, [this](char const* p) { c_main->decodeLevel(p); });
+popHandler(); // key: decodeLevel
+pushKey("decrypt");
+addBare([this]() { c_main->decrypt(); });
+popHandler(); // key: decrypt
+pushKey("staticAesIv");
+addBare([this]() { c_main->staticAesIv(); });
+popHandler(); // key: staticAesIv
+pushKey("staticId");
+addBare([this]() { c_main->staticId(); });
+popHandler(); // key: staticId
+pushKey("noOriginalObjectIds");
+addBare([this]() { c_main->noOriginalObjectIds(); });
+popHandler(); // key: noOriginalObjectIds
+pushKey("copyEncryption");
+addParameter([this](char const* p) { c_main->copyEncryption(p); });
+popHandler(); // key: copyEncryption
+pushKey("encryptionFilePassword");
+addParameter([this](char const* p) { c_main->encryptionFilePassword(p); });
+popHandler(); // key: encryptionFilePassword
+pushKey("linearize");
+addBare([this]() { c_main->linearize(); });
+popHandler(); // key: linearize
+pushKey("linearizePass1");
+addParameter([this](char const* p) { c_main->linearizePass1(p); });
+popHandler(); // key: linearizePass1
+pushKey("objectStreams");
+addChoices(object_streams_choices, [this](char const* p) { c_main->objectStreams(p); });
+popHandler(); // key: objectStreams
+pushKey("minVersion");
+addParameter([this](char const* p) { c_main->minVersion(p); });
+popHandler(); // key: minVersion
+pushKey("forceVersion");
+addParameter([this](char const* p) { c_main->forceVersion(p); });
+popHandler(); // key: forceVersion
+pushKey("progress");
+addBare([this]() { c_main->progress(); });
+popHandler(); // key: progress
+pushKey("splitPages");
+addParameter([this](char const* p) { c_main->splitPages(p); });
+popHandler(); // key: splitPages
+pushKey("encrypt");
+beginDict(bindJSON(&Handlers::beginOutputOptionsEncrypt), bindBare(&Handlers::endOutputOptionsEncrypt)); // .output.options.encrypt
+pushKey("userPassword");
+setupOutputOptionsEncryptUserPassword();
+popHandler(); // key: userPassword
+pushKey("ownerPassword");
+setupOutputOptionsEncryptOwnerPassword();
+popHandler(); // key: ownerPassword
+pushKey("40bit");
+beginDict(bindJSON(&Handlers::beginOutputOptionsEncrypt40bit), bindBare(&Handlers::endOutputOptionsEncrypt40bit)); // .output.options.encrypt.40bit
+pushKey("annotate");
+addChoices(yn_choices, [this](char const* p) { c_enc->annotate(p); });
+popHandler(); // key: annotate
+pushKey("extract");
+addChoices(yn_choices, [this](char const* p) { c_enc->extract(p); });
+popHandler(); // key: extract
+pushKey("modify");
+addChoices(modify128_choices, [this](char const* p) { c_enc->modify(p); });
+popHandler(); // key: modify
+pushKey("print");
+addChoices(print128_choices, [this](char const* p) { c_enc->print(p); });
+popHandler(); // key: print
+popHandler(); // key: 40bit
+pushKey("128bit");
+beginDict(bindJSON(&Handlers::beginOutputOptionsEncrypt128bit), bindBare(&Handlers::endOutputOptionsEncrypt128bit)); // .output.options.encrypt.128bit
+pushKey("accessibility");
+addChoices(yn_choices, [this](char const* p) { c_enc->accessibility(p); });
+popHandler(); // key: accessibility
+pushKey("annotate");
+addChoices(yn_choices, [this](char const* p) { c_enc->annotate(p); });
+popHandler(); // key: annotate
+pushKey("assemble");
+addChoices(yn_choices, [this](char const* p) { c_enc->assemble(p); });
+popHandler(); // key: assemble
+pushKey("cleartextMetadata");
+addBare([this]() { c_enc->cleartextMetadata(); });
+popHandler(); // key: cleartextMetadata
+pushKey("extract");
+addChoices(yn_choices, [this](char const* p) { c_enc->extract(p); });
+popHandler(); // key: extract
+pushKey("form");
+addChoices(yn_choices, [this](char const* p) { c_enc->form(p); });
+popHandler(); // key: form
+pushKey("modifyOther");
+addChoices(yn_choices, [this](char const* p) { c_enc->modifyOther(p); });
+popHandler(); // key: modifyOther
+pushKey("modify");
+addChoices(modify128_choices, [this](char const* p) { c_enc->modify(p); });
+popHandler(); // key: modify
+pushKey("print");
+addChoices(print128_choices, [this](char const* p) { c_enc->print(p); });
+popHandler(); // key: print
+pushKey("forceV4");
+addBare([this]() { c_enc->forceV4(); });
+popHandler(); // key: forceV4
+pushKey("useAes");
+addChoices(yn_choices, [this](char const* p) { c_enc->useAes(p); });
+popHandler(); // key: useAes
+popHandler(); // key: 128bit
+pushKey("256bit");
+beginDict(bindJSON(&Handlers::beginOutputOptionsEncrypt256bit), bindBare(&Handlers::endOutputOptionsEncrypt256bit)); // .output.options.encrypt.256bit
+pushKey("accessibility");
+addChoices(yn_choices, [this](char const* p) { c_enc->accessibility(p); });
+popHandler(); // key: accessibility
+pushKey("annotate");
+addChoices(yn_choices, [this](char const* p) { c_enc->annotate(p); });
+popHandler(); // key: annotate
+pushKey("assemble");
+addChoices(yn_choices, [this](char const* p) { c_enc->assemble(p); });
+popHandler(); // key: assemble
+pushKey("cleartextMetadata");
+addBare([this]() { c_enc->cleartextMetadata(); });
+popHandler(); // key: cleartextMetadata
+pushKey("extract");
+addChoices(yn_choices, [this](char const* p) { c_enc->extract(p); });
+popHandler(); // key: extract
+pushKey("form");
+addChoices(yn_choices, [this](char const* p) { c_enc->form(p); });
+popHandler(); // key: form
+pushKey("modifyOther");
+addChoices(yn_choices, [this](char const* p) { c_enc->modifyOther(p); });
+popHandler(); // key: modifyOther
+pushKey("modify");
+addChoices(modify128_choices, [this](char const* p) { c_enc->modify(p); });
+popHandler(); // key: modify
+pushKey("print");
+addChoices(print128_choices, [this](char const* p) { c_enc->print(p); });
+popHandler(); // key: print
+pushKey("allowInsecure");
+addBare([this]() { c_enc->allowInsecure(); });
+popHandler(); // key: allowInsecure
+pushKey("forceR5");
+addBare([this]() { c_enc->forceR5(); });
+popHandler(); // key: forceR5
+popHandler(); // key: 256bit
+popHandler(); // key: encrypt
+popHandler(); // key: options
+popHandler(); // key: output
+pushKey("inspect");
+beginDict(bindJSON(&Handlers::beginInspect), bindBare(&Handlers::endInspect)); // .inspect
+pushKey("check");
+addBare([this]() { c_main->check(); });
+popHandler(); // key: check
+pushKey("checkLinearization");
+addBare([this]() { c_main->checkLinearization(); });
+popHandler(); // key: checkLinearization
+pushKey("filteredStreamData");
+addBare([this]() { c_main->filteredStreamData(); });
+popHandler(); // key: filteredStreamData
+pushKey("rawStreamData");
+addBare([this]() { c_main->rawStreamData(); });
+popHandler(); // key: rawStreamData
+pushKey("showEncryption");
+addBare([this]() { c_main->showEncryption(); });
+popHandler(); // key: showEncryption
+pushKey("showEncryptionKey");
+addBare([this]() { c_main->showEncryptionKey(); });
+popHandler(); // key: showEncryptionKey
+pushKey("showLinearization");
+addBare([this]() { c_main->showLinearization(); });
+popHandler(); // key: showLinearization
+pushKey("showNpages");
+addBare([this]() { c_main->showNpages(); });
+popHandler(); // key: showNpages
+pushKey("showObject");
+addParameter([this](char const* p) { c_main->showObject(p); });
+popHandler(); // key: showObject
+pushKey("showPages");
+addBare([this]() { c_main->showPages(); });
+popHandler(); // key: showPages
+pushKey("showXref");
+addBare([this]() { c_main->showXref(); });
+popHandler(); // key: showXref
+pushKey("withImages");
+addBare([this]() { c_main->withImages(); });
+popHandler(); // key: withImages
+pushKey("listAttachments");
+addBare([this]() { c_main->listAttachments(); });
+popHandler(); // key: listAttachments
+pushKey("showAttachment");
+addParameter([this](char const* p) { c_main->showAttachment(p); });
+popHandler(); // key: showAttachment
+pushKey("json");
+addBare([this]() { c_main->json(); });
+popHandler(); // key: json
+pushKey("jsonKey");
+beginArray(bindJSON(&Handlers::beginInspectJsonKeyArray), bindBare(&Handlers::endInspectJsonKeyArray)); // .inspect.jsonKey[]
+addChoices(json_key_choices, [this](char const* p) { c_main->jsonKey(p); });
+popHandler(); // array: .inspect.jsonKey[]
+popHandler(); // key: jsonKey
+pushKey("jsonObject");
+beginArray(bindJSON(&Handlers::beginInspectJsonObjectArray), bindBare(&Handlers::endInspectJsonObjectArray)); // .inspect.jsonObject[]
+addParameter([this](char const* p) { c_main->jsonObject(p); });
+popHandler(); // array: .inspect.jsonObject[]
+popHandler(); // key: jsonObject
+popHandler(); // key: inspect
+pushKey("options");
+beginDict(bindJSON(&Handlers::beginOptions), bindBare(&Handlers::endOptions)); // .options
+pushKey("allowWeakCrypto");
+addBare([this]() { c_main->allowWeakCrypto(); });
+popHandler(); // key: allowWeakCrypto
+pushKey("deterministicId");
+addBare([this]() { c_main->deterministicId(); });
+popHandler(); // key: deterministicId
+pushKey("keepFilesOpen");
+addChoices(yn_choices, [this](char const* p) { c_main->keepFilesOpen(p); });
+popHandler(); // key: keepFilesOpen
+pushKey("keepFilesOpenThreshold");
+addParameter([this](char const* p) { c_main->keepFilesOpenThreshold(p); });
+popHandler(); // key: keepFilesOpenThreshold
+pushKey("noWarn");
+addBare([this]() { c_main->noWarn(); });
+popHandler(); // key: noWarn
+pushKey("verbose");
+addBare([this]() { c_main->verbose(); });
+popHandler(); // key: verbose
+pushKey("ignoreXrefStreams");
+addBare([this]() { c_main->ignoreXrefStreams(); });
+popHandler(); // key: ignoreXrefStreams
+pushKey("passwordIsHexKey");
+addBare([this]() { c_main->passwordIsHexKey(); });
+popHandler(); // key: passwordIsHexKey
+pushKey("passwordMode");
+addChoices(password_mode_choices, [this](char const* p) { c_main->passwordMode(p); });
+popHandler(); // key: passwordMode
+pushKey("suppressPasswordRecovery");
+addBare([this]() { c_main->suppressPasswordRecovery(); });
+popHandler(); // key: suppressPasswordRecovery
+pushKey("suppressRecovery");
+addBare([this]() { c_main->suppressRecovery(); });
+popHandler(); // key: suppressRecovery
+pushKey("coalesceContents");
+addBare([this]() { c_main->coalesceContents(); });
+popHandler(); // key: coalesceContents
+pushKey("compressionLevel");
+addParameter([this](char const* p) { c_main->compressionLevel(p); });
+popHandler(); // key: compressionLevel
+pushKey("externalizeInlineImages");
+addBare([this]() { c_main->externalizeInlineImages(); });
+popHandler(); // key: externalizeInlineImages
+pushKey("iiMinBytes");
+addParameter([this](char const* p) { c_main->iiMinBytes(p); });
+popHandler(); // key: iiMinBytes
+pushKey("removeUnreferencedResources");
+addChoices(remove_unref_choices, [this](char const* p) { c_main->removeUnreferencedResources(p); });
+popHandler(); // key: removeUnreferencedResources
+pushKey("addAttachment");
+beginArray(bindJSON(&Handlers::beginOptionsAddAttachmentArray), bindBare(&Handlers::endOptionsAddAttachmentArray)); // .options.addAttachment[]
+beginDict(bindJSON(&Handlers::beginOptionsAddAttachment), bindBare(&Handlers::endOptionsAddAttachment)); // .options.addAttachment
+pushKey("path");
+setupOptionsAddAttachmentPath();
+popHandler(); // key: path
+pushKey("creationdate");
+addParameter([this](char const* p) { c_att->creationdate(p); });
+popHandler(); // key: creationdate
+pushKey("description");
+addParameter([this](char const* p) { c_att->description(p); });
+popHandler(); // key: description
+pushKey("filename");
+addParameter([this](char const* p) { c_att->filename(p); });
+popHandler(); // key: filename
+pushKey("key");
+addParameter([this](char const* p) { c_att->key(p); });
+popHandler(); // key: key
+pushKey("mimetype");
+addParameter([this](char const* p) { c_att->mimetype(p); });
+popHandler(); // key: mimetype
+pushKey("moddate");
+addParameter([this](char const* p) { c_att->moddate(p); });
+popHandler(); // key: moddate
+pushKey("replace");
+addBare([this]() { c_att->replace(); });
+popHandler(); // key: replace
+popHandler(); // array: .options.addAttachment[]
+popHandler(); // key: addAttachment
+pushKey("removeAttachment");
+addParameter([this](char const* p) { c_main->removeAttachment(p); });
+popHandler(); // key: removeAttachment
+pushKey("copyAttachmentsFrom");
+beginArray(bindJSON(&Handlers::beginOptionsCopyAttachmentsFromArray), bindBare(&Handlers::endOptionsCopyAttachmentsFromArray)); // .options.copyAttachmentsFrom[]
+beginDict(bindJSON(&Handlers::beginOptionsCopyAttachmentsFrom), bindBare(&Handlers::endOptionsCopyAttachmentsFrom)); // .options.copyAttachmentsFrom
+pushKey("path");
+setupOptionsCopyAttachmentsFromPath();
+popHandler(); // key: path
+pushKey("password");
+setupOptionsCopyAttachmentsFromPassword();
+popHandler(); // key: password
+pushKey("prefix");
+addParameter([this](char const* p) { c_copy_att->prefix(p); });
+popHandler(); // key: prefix
+popHandler(); // array: .options.copyAttachmentsFrom[]
+popHandler(); // key: copyAttachmentsFrom
+pushKey("collate");
+addParameter([this](char const* p) { c_main->collate(p); });
+popHandler(); // key: collate
+pushKey("flattenAnnotations");
+addChoices(flatten_choices, [this](char const* p) { c_main->flattenAnnotations(p); });
+popHandler(); // key: flattenAnnotations
+pushKey("flattenRotation");
+addBare([this]() { c_main->flattenRotation(); });
+popHandler(); // key: flattenRotation
+pushKey("generateAppearances");
+addBare([this]() { c_main->generateAppearances(); });
+popHandler(); // key: generateAppearances
+pushKey("keepInlineImages");
+addBare([this]() { c_main->keepInlineImages(); });
+popHandler(); // key: keepInlineImages
+pushKey("oiMinArea");
+addParameter([this](char const* p) { c_main->oiMinArea(p); });
+popHandler(); // key: oiMinArea
+pushKey("oiMinHeight");
+addParameter([this](char const* p) { c_main->oiMinHeight(p); });
+popHandler(); // key: oiMinHeight
+pushKey("oiMinWidth");
+addParameter([this](char const* p) { c_main->oiMinWidth(p); });
+popHandler(); // key: oiMinWidth
+pushKey("optimizeImages");
+addBare([this]() { c_main->optimizeImages(); });
+popHandler(); // key: optimizeImages
+pushKey("pages");
+beginArray(bindJSON(&Handlers::beginOptionsPagesArray), bindBare(&Handlers::endOptionsPagesArray)); // .options.pages[]
+beginDict(bindJSON(&Handlers::beginOptionsPages), bindBare(&Handlers::endOptionsPages)); // .options.pages
+pushKey("file");
+setupOptionsPagesFile();
+popHandler(); // key: file
+pushKey("password");
+setupOptionsPagesPassword();
+popHandler(); // key: password
+pushKey("range");
+setupOptionsPagesRange();
+popHandler(); // key: range
+popHandler(); // array: .options.pages[]
+popHandler(); // key: pages
+pushKey("removePageLabels");
+addBare([this]() { c_main->removePageLabels(); });
+popHandler(); // key: removePageLabels
+pushKey("rotate");
+addParameter([this](char const* p) { c_main->rotate(p); });
+popHandler(); // key: rotate
+pushKey("overlay");
+beginDict(bindJSON(&Handlers::beginOptionsOverlay), bindBare(&Handlers::endOptionsOverlay)); // .options.overlay
+pushKey("file");
+setupOptionsOverlayFile();
+popHandler(); // key: file
+pushKey("password");
+setupOptionsOverlayPassword();
+popHandler(); // key: password
+pushKey("from");
+addParameter([this](char const* p) { c_uo->from(p); });
+popHandler(); // key: from
+pushKey("repeat");
+addParameter([this](char const* p) { c_uo->repeat(p); });
+popHandler(); // key: repeat
+pushKey("to");
+addParameter([this](char const* p) { c_uo->to(p); });
+popHandler(); // key: to
+popHandler(); // key: overlay
+pushKey("underlay");
+beginDict(bindJSON(&Handlers::beginOptionsUnderlay), bindBare(&Handlers::endOptionsUnderlay)); // .options.underlay
+pushKey("file");
+setupOptionsUnderlayFile();
+popHandler(); // key: file
+pushKey("password");
+setupOptionsUnderlayPassword();
+popHandler(); // key: password
+pushKey("from");
+addParameter([this](char const* p) { c_uo->from(p); });
+popHandler(); // key: from
+pushKey("repeat");
+addParameter([this](char const* p) { c_uo->repeat(p); });
+popHandler(); // key: repeat
+pushKey("to");
+addParameter([this](char const* p) { c_uo->to(p); });
+popHandler(); // key: to
+popHandler(); // key: underlay
+popHandler(); // key: options
diff --git a/libqpdf/qpdf/auto_job_schema.hh b/libqpdf/qpdf/auto_job_schema.hh
index ba5c93df..2a621ac9 100644
--- a/libqpdf/qpdf/auto_job_schema.hh
+++ b/libqpdf/qpdf/auto_job_schema.hh
@@ -85,10 +85,10 @@ static constexpr char const* JOB_SCHEMA_DATA = R"({
"showAttachment": "export an embedded file",
"json": "show file in json format",
"jsonKey": [
- null
+ "restrict which keys are in json output"
],
"jsonObject": [
- null
+ "restrict which objects are in JSON"
]
},
"options": {