diff --git a/TODO b/TODO index d46a2821..61de004d 100644 --- a/TODO +++ b/TODO @@ -69,24 +69,9 @@ Soon: Break ground on "Document-level work" JSON v2 fixes ============= -* Get rid of separate format for --json and --json-output. Instead, - --json-output can just require an outfile and change some defaults - like which keys are present and json-stream-data. This makes it - easier to support use cases like being able to use information in - other top-level keys ("pages", "attachments", etc.) to drive - modifications made to objects without having to run qpdf twice. I - think --json-output should make the default key be only "qpdf" and - the default json-stream-data mode be inline, but make it so you can - use --json-stream-data and --json-stream-prefix with --json and - --json-keys with --json-output. These would be exactly the same: - - --json-output --json-keys=all - - --json --json-stream-data=inline - - And these: - - --json-output - - --json --json-stream-data=inline --json-key=qpdf +* Unify code between QPDFJob::doJSONObjects and QPDF::writeJSON. Make + sure that the "qpdf" key is always present when json-output is + specified. * Change the name of the "qpdf-v2" key to "qpdf". Use that in place of "objects" and change its content to a two-element array whose first @@ -114,9 +99,10 @@ JSON v2 fixes This implies a few things: - * QPDF::writeJSON will have to take an argument indicating whether - additional keys are being written which determines whether it - outputs the outer braces or not. + * Fix --json-help + + * --json-key=objects is only valid for v1. --json-key=qpdf is only + valid for v2. * This changes the policy about additional extra keys. Have a guarantee that qpdf will never add a key whose name is or starts diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh index a80ddcd5..639e16c4 100644 --- a/include/qpdf/QPDF.hh +++ b/include/qpdf/QPDF.hh @@ -134,8 +134,17 @@ class QPDF void updateFromJSON(std::shared_ptr); // Write qpdf json format to the pipeline "p". The only supported - // version is 2. The finish() method is called on the pipeline at - // the end. The decode_level parameter controls which streams are + // version is 2. + // + // If the value of "complete" is true, a complete JSON object + // containing only the "qpdf" key is written to the pipeline, and + // finish() is called on the pipeline at the end. If the value of + // "complete" is false, the "qpdf" key and its value are written + // to the pipeline assuming that a dictionary is already open, and + // finish() is not called. The parameter first_key indicates + // whether this is the first key if in-progress dictionary. + // + // The decode_level parameter controls which streams are // uncompressed in the JSON. Use qpdf_dl_none to preserve all // stream data exactly as it appears in the input. The possible // values for json_stream_data can be found in qpdf/Constants.h @@ -158,6 +167,8 @@ class QPDF void writeJSON( int version, Pipeline* p, + bool complete, + bool first_key, qpdf_stream_decode_level_e decode_level, qpdf_json_stream_data_e json_stream_data, std::string const& file_prefix, diff --git a/job.sums b/job.sums index 4877ed8f..9b715478 100644 --- a/job.sums +++ b/job.sums @@ -8,10 +8,10 @@ include/qpdf/auto_job_c_pages.hh b3cc0f21029f6d89efa043dcdbfa183cb59325b6506001c include/qpdf/auto_job_c_uo.hh ae21b69a1efa9333050f4833d465f6daff87e5b38e5106e49bbef5d4132e4ed1 job.yml 3b2b3c6f92b48f6c76109711cbfdd74669fa31a80cd17379548b09f8e76be05d libqpdf/qpdf/auto_job_decl.hh 74df4d7fdbdf51ecd0d58ce1e9844bb5525b9adac5a45f7c9a787ecdda2868df -libqpdf/qpdf/auto_job_help.hh 3aaae4cde004e5314d3ac6d554da575e40209c0f0611f6a308957986f9c7967b +libqpdf/qpdf/auto_job_help.hh db2e4350c700e064b204e3e20d4fee4eddfe312b28092afcf608b4b6863d30e5 libqpdf/qpdf/auto_job_init.hh 7ea8e0641dc26fdfba6e283e14dbbff0c016654e174cdace8054f8bef53750fd libqpdf/qpdf/auto_job_json_decl.hh 06caa46eaf71db8a50c046f91866baa8087745a9474319fb7c86d92634cc8297 libqpdf/qpdf/auto_job_json_init.hh 5f6b53e3c81d4b54ce5c4cf9c3f52d0c02f987c53bf8841c0280367bad23e335 libqpdf/qpdf/auto_job_schema.hh 9d543cd4a43eafffc2c4b8a6fee29e399c271c52cb6f7d417ae5497b3c1127dc manual/_ext/qpdf.py 6add6321666031d55ed4aedf7c00e5662bba856dfcd66ccb526563bffefbb580 -manual/cli.rst ad8b234c24569e41c7929f729bb2188f86cd94b8fea5905b71802673cec92eed +manual/cli.rst 8e1f443c6fa000e023e516c318df4d04d58233d4d8648907c4a71f0ea5722bca diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc index 06e93704..ae717218 100644 --- a/libqpdf/QPDFJob.cc +++ b/libqpdf/QPDFJob.cc @@ -3381,6 +3381,8 @@ QPDFJob::writeJSON(QPDF& pdf) pdf.writeJSON( this->m->json_output, fp.get(), + true, + true, this->m->decode_level, this->m->json_stream_data, file_prefix, diff --git a/libqpdf/QPDFJob_config.cc b/libqpdf/QPDFJob_config.cc index 0192346e..6a500b5c 100644 --- a/libqpdf/QPDFJob_config.cc +++ b/libqpdf/QPDFJob_config.cc @@ -312,6 +312,9 @@ QPDFJob::Config::jsonOutput(std::string const& parameter) if (!o.m->decode_level_set) { o.m->decode_level = qpdf_dl_none; } + if (o.m->json_keys.empty()) { + o.m->json_keys.insert("qpdf"); + } return this; } diff --git a/libqpdf/QPDF_json.cc b/libqpdf/QPDF_json.cc index 59aac05e..81f21f8a 100644 --- a/libqpdf/QPDF_json.cc +++ b/libqpdf/QPDF_json.cc @@ -764,6 +764,8 @@ void QPDF::writeJSON( int version, Pipeline* p, + bool complete, + bool first_key, qpdf_stream_decode_level_e decode_level, qpdf_json_stream_data_e json_stream_data, std::string const& file_prefix, @@ -818,7 +820,9 @@ QPDF::writeJSON( } JSON::writeDictionaryClose(p, first_object, 2); JSON::writeDictionaryClose(p, first_qpdf, 1); - JSON::writeDictionaryClose(p, first, 0); - *p << "\n"; - p->finish(); + if (complete) { + JSON::writeDictionaryClose(p, first, 0); + *p << "\n"; + p->finish(); + } } diff --git a/libqpdf/qpdf/auto_job_help.hh b/libqpdf/qpdf/auto_job_help.hh index 5146ddae..6ade99f5 100644 --- a/libqpdf/qpdf/auto_job_help.hh +++ b/libqpdf/qpdf/auto_job_help.hh @@ -821,16 +821,18 @@ objects will be shown. )"); ap.addOptionHelp("--json-stream-data", "json", "how to handle streams in json output", R"(--json-stream-data={none|inline|file} -When used with --json-output, this option controls whether -streams in json output should be omitted, written inline -(base64-encoded) or written to a file. If "file" is chosen, the -file will be the name of the output file appended with -nnn where -nnn is the object number. The prefix can be overridden with ---json-stream-prefix. +When used with --json, this option controls whether streams in +json output should be omitted, written inline (base64-encoded) +or written to a file. If "file" is chosen, the file will be the +name of the output file appended with -nnn where nnn is the +object number. The prefix can be overridden with +--json-stream-prefix. The default is "none", except +when --json-output is specified, in which case the default is +"inline". )"); ap.addOptionHelp("--json-stream-prefix", "json", "prefix for json stream data files", R"(--json-stream-prefix=file-prefix -When used with --json-output, --json-stream-data=file-prefix +When used with --json-stream-data=file, --json-stream-data=file-prefix sets the prefix for stream data files, overriding the default, which is to use the output file name. Whatever is given here will be appended with -nnn to create the name of the file that diff --git a/manual/cli.rst b/manual/cli.rst index 9332758a..809437b7 100644 --- a/manual/cli.rst +++ b/manual/cli.rst @@ -3220,7 +3220,9 @@ Related Options This option is repeatable. If given, only the specified top-level keys will be included in the JSON output. Otherwise, all keys will be included. ``version`` and ``parameters`` will always appear in - the output. + the output. If not given, all keys will be included, unless + :qpdf:ref:`--json-output` was specified, in which case, only the + ``"qpdf"`` key will be included by default. .. qpdf:option:: --json-object={trailer|obj[,gen]} @@ -3241,39 +3243,41 @@ Related Options .. help: how to handle streams in json output - When used with --json-output, this option controls whether - streams in json output should be omitted, written inline - (base64-encoded) or written to a file. If "file" is chosen, the - file will be the name of the output file appended with -nnn where - nnn is the object number. The prefix can be overridden with - --json-stream-prefix. + When used with --json, this option controls whether streams in + json output should be omitted, written inline (base64-encoded) + or written to a file. If "file" is chosen, the file will be the + name of the output file appended with -nnn where nnn is the + object number. The prefix can be overridden with + --json-stream-prefix. The default is "none", except + when --json-output is specified, in which case the default is + "inline". - When used with :qpdf:ref:`--json-output`, this option controls + When used with :qpdf:ref:`--json`, this option controls whether streams in JSON output should be omitted, written inline (base64-encoded) or written to a file. If ``file`` is chosen, the file will be the name of the output file appended with :samp:`-{nnn}` where :samp:`{nnn}` is the object number. The stream data file prefix can be overridden with - :qpdf:ref:`--json-stream-prefix`. This option only applies when - used with :qpdf:ref:`--json-output`. + :qpdf:ref:`--json-stream-prefix`. The default value is ``none``, + except when :qpdf:ref:`--json-output` is specified, in which case + the default is ``inline``. .. qpdf:option:: --json-stream-prefix=file-prefix .. help: prefix for json stream data files - When used with --json-output, --json-stream-data=file-prefix + When used with --json-stream-data=file, --json-stream-data=file-prefix sets the prefix for stream data files, overriding the default, which is to use the output file name. Whatever is given here will be appended with -nnn to create the name of the file that will contain the data for the stream stream in object nnn. - When used with :qpdf:ref:`--json-output`, + When used with ``--json-stream-data=file``, ``--json-stream-data=file-prefix`` sets the prefix for stream data files, overriding the default, which is to use the output file name. Whatever is given here will be appended with :samp:`-{nnn}` to create the name of the file that will contain the data for the - stream stream in object :samp:`{nnn}`. This option only applies - when used with :qpdf:ref:`--json-output`. + stream stream in object :samp:`{nnn}`. .. qpdf:option:: --json-output[=version] @@ -3288,12 +3292,22 @@ Related Options in qpdf JSON format at the given version. ``version`` may be a specific version or ``latest`` (the default). The only supported version is 2. See also :qpdf:ref:`--json-stream-data` and - :qpdf:ref:`--json-stream-prefix`. When this option is specified, - the default decode level for stream data is ``none``, but you can - override it with :qpdf:ref:`--decode-level`. If you want to look at - the contents of streams easily as you would in QDF mode (see - :ref:`qdf`), you can use ``--decode-level=generalized`` and - ``--json-stream-data=file`` for a convenient way to do that. + :qpdf:ref:`--json-stream-prefix`. This option also changes the + following defaults: + + - The default value for :qpdf:ref:`--json-stream-data` changes from + ``none`` to ``inline``. + + - The default decode level for stream data becomes ``none``, but you can + override it with :qpdf:ref:`--decode-level`. + + - Only the ``"qpdf"`` key is included in the JSON output, but you + can add additional keys with :qpdf:ref:`--json-key`. + + If you want to look at the contents of streams easily as you would + in QDF mode (see :ref:`qdf`), you can use + ``--decode-level=generalized`` and ``--json-stream-data=file`` for + a convenient way to do that. .. qpdf:option:: --json-input