This commit is contained in:
nlohmann committed 2026-11-13 23:26:50 +00:00
1 parent 0c4c69e37d
commit 9f62284716
22 files changed
+138 -88

No files matched your search

+3 -1
View File
@@ -58,7 +58,9 @@ is not UTF-8 encoded and `error_handler` is set to `strict`
## Complexity
Linear.
Linear in the size of the result. With an `indent`, every line starts with up to `indent` characters per nesting level,
so the result can be larger than the value by a factor of its nesting depth (see
[Parsing untrusted input](../../features/parsing/untrusted_input.md#nesting-depth)).
## Notes
+2 -2
View File
@@ -2,7 +2,7 @@
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=kt>char</span><span class=w> </span><span class=n>indent_char</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=sc>' '</span><span class=p>,</span>
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=n>ensure_ascii</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=nb>false</span><span class=p>,</span>
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>error_handler_t</span><span class=w> </span><span class=n>error_handler</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>error_handler_t</span><span class=o>::</span><span class=n>strict</span><span class=p>)</span><span class=w> </span><span class=k>const</span><span class=p>;</span>
</code></pre></div> <p>Serialization function for <abbr title="JavaScript Object Notation">JSON</abbr> values. The function tries to mimic Python's <a href="https://docs.python.org/2/library/json.html#json.dump"><code>json.dumps()</code> function</a>, and currently supports its <code>indent</code> and <code>ensure_ascii</code> parameters.</p> <h2 id=parameters>Parameters<a class=headerlink href=#parameters title="Permanent link">&para;</a></h2> <dl> <dt><code>indent</code> (in)</dt> <dd>If <code>indent</code> is nonnegative, then array elements and object members will be pretty-printed with that indent level. An indent level of <code>0</code> will only insert newlines. <code>-1</code> (the default) selects the most compact representation.</dd> <dt><code>indent_char</code> (in)</dt> <dd>The character to use for indentation if <code>indent</code> is greater than <code>0</code>. The default is <code></code> (space).</dd> <dt><code>ensure_ascii</code> (in)</dt> <dd>If <code>ensure_ascii</code> is true, all non-<abbr title="American Standard Code for Information Interchange">ASCII</abbr> characters in the output are escaped with <code>\uXXXX</code> sequences, and the result consists of <abbr title="American Standard Code for Information Interchange">ASCII</abbr> characters only.</dd> <dt><code>error_handler</code> (in)</dt> <dd>how to react on decoding errors; there are four possible values (see <a href=../error_handler_t/ ><code>error_handler_t</code></a>: <code>strict</code> (throws an exception in case a decoding error occurs; default), <code>replace</code> (replace invalid <abbr title="Unicode Transformation Format">UTF</abbr>-8 sequences with U+FFFD), <code>ignore</code> (ignore invalid <abbr title="Unicode Transformation Format">UTF</abbr>-8 sequences during serialization; all valid bytes are copied to the output unchanged, and invalid bytes are dropped), and <code>keep</code> (write the ill-formed bytes to the output as is, without escaping them, even if <code>ensure_ascii</code> is <code class=highlight><span class=nb>true</span></code>; the result is then not valid <abbr title="Unicode Transformation Format">UTF</abbr>-8, but equals the input bytes exactly, and well-formed characters around the ill-formed bytes are still escaped as usual)).</dd> </dl> <h2 id=return-value>Return value<a class=headerlink href=#return-value title="Permanent link">&para;</a></h2> <p>string containing the serialization of the <abbr title="JavaScript Object Notation">JSON</abbr> value</p> <h2 id=exception-safety>Exception safety<a class=headerlink href=#exception-safety title="Permanent link">&para;</a></h2> <p>Strong guarantee: if an exception is thrown, there are no changes to any <abbr title="JavaScript Object Notation">JSON</abbr> value.</p> <h2 id=exceptions>Exceptions<a class=headerlink href=#exceptions title="Permanent link">&para;</a></h2> <p>Throws <a href=../../../home/exceptions/#jsonexceptiontype_error316><code>type_error.316</code></a> if a string stored inside the <abbr title="JavaScript Object Notation">JSON</abbr> value is not <abbr title="Unicode Transformation Format">UTF</abbr>-8 encoded and <code>error_handler</code> is set to <code>strict</code></p> <div class="admonition warning"> <p class=admonition-title>Serializing untrusted input</p> <p>When serializing values that may contain invalid or untrusted <abbr title="Unicode Transformation Format">UTF</abbr>-8 (e.g., bytes taken directly from network input), <code>dump()</code> throws <a href=../../../home/exceptions/#jsonexceptiontype_error316><code>type_error.316</code></a> in the default <code>strict</code> mode. To serialize such data without throwing, pass <a href=../error_handler_t/ ><code>error_handler_t::replace</code></a> (substitutes U+FFFD) or <a href=../error_handler_t/ ><code>error_handler_t::ignore</code></a>. Callers that serialize untrusted input on a crash-sensitive path should either choose a non-strict error handler or wrap <code>dump()</code> in a <code class=highlight><span class=k>try</span></code>/<code class=highlight><span class=k>catch</span></code>.</p> <p>See the <a href=../../../home/faq/#serializing-untrusted-or-invalid-utf-8><abbr title="Frequently Asked Questions">FAQ</abbr></a> for details.</p> </div> <h2 id=complexity>Complexity<a class=headerlink href=#complexity title="Permanent link">&para;</a></h2> <p>Linear.</p> <h2 id=notes>Notes<a class=headerlink href=#notes title="Permanent link">&para;</a></h2> <p>Floating-point numbers are written with the fewest digits that read back as the same value (for <code class=highlight><span class=kt>double</span></code>; see <a href=../../../features/types/number_handling/#number-serialization>number handling</a>).</p> <p>Binary values are serialized as an object containing two keys:</p> <ul> <li>"bytes": an array of bytes as integers</li> <li>"subtype": the subtype as integer or <code class=highlight><span class=kc>null</span></code> if the binary has no subtype</li> </ul> <h2 id=exaLine truncated
</code></pre></div> <p>Serialization function for <abbr title="JavaScript Object Notation">JSON</abbr> values. The function tries to mimic Python's <a href="https://docs.python.org/2/library/json.html#json.dump"><code>json.dumps()</code> function</a>, and currently supports its <code>indent</code> and <code>ensure_ascii</code> parameters.</p> <h2 id=parameters>Parameters<a class=headerlink href=#parameters title="Permanent link">&para;</a></h2> <dl> <dt><code>indent</code> (in)</dt> <dd>If <code>indent</code> is nonnegative, then array elements and object members will be pretty-printed with that indent level. An indent level of <code>0</code> will only insert newlines. <code>-1</code> (the default) selects the most compact representation.</dd> <dt><code>indent_char</code> (in)</dt> <dd>The character to use for indentation if <code>indent</code> is greater than <code>0</code>. The default is <code></code> (space).</dd> <dt><code>ensure_ascii</code> (in)</dt> <dd>If <code>ensure_ascii</code> is true, all non-<abbr title="American Standard Code for Information Interchange">ASCII</abbr> characters in the output are escaped with <code>\uXXXX</code> sequences, and the result consists of <abbr title="American Standard Code for Information Interchange">ASCII</abbr> characters only.</dd> <dt><code>error_handler</code> (in)</dt> <dd>how to react on decoding errors; there are four possible values (see <a href=../error_handler_t/ ><code>error_handler_t</code></a>: <code>strict</code> (throws an exception in case a decoding error occurs; default), <code>replace</code> (replace invalid <abbr title="Unicode Transformation Format">UTF</abbr>-8 sequences with U+FFFD), <code>ignore</code> (ignore invalid <abbr title="Unicode Transformation Format">UTF</abbr>-8 sequences during serialization; all valid bytes are copied to the output unchanged, and invalid bytes are dropped), and <code>keep</code> (write the ill-formed bytes to the output as is, without escaping them, even if <code>ensure_ascii</code> is <code class=highlight><span class=nb>true</span></code>; the result is then not valid <abbr title="Unicode Transformation Format">UTF</abbr>-8, but equals the input bytes exactly, and well-formed characters around the ill-formed bytes are still escaped as usual)).</dd> </dl> <h2 id=return-value>Return value<a class=headerlink href=#return-value title="Permanent link">&para;</a></h2> <p>string containing the serialization of the <abbr title="JavaScript Object Notation">JSON</abbr> value</p> <h2 id=exception-safety>Exception safety<a class=headerlink href=#exception-safety title="Permanent link">&para;</a></h2> <p>Strong guarantee: if an exception is thrown, there are no changes to any <abbr title="JavaScript Object Notation">JSON</abbr> value.</p> <h2 id=exceptions>Exceptions<a class=headerlink href=#exceptions title="Permanent link">&para;</a></h2> <p>Throws <a href=../../../home/exceptions/#jsonexceptiontype_error316><code>type_error.316</code></a> if a string stored inside the <abbr title="JavaScript Object Notation">JSON</abbr> value is not <abbr title="Unicode Transformation Format">UTF</abbr>-8 encoded and <code>error_handler</code> is set to <code>strict</code></p> <div class="admonition warning"> <p class=admonition-title>Serializing untrusted input</p> <p>When serializing values that may contain invalid or untrusted <abbr title="Unicode Transformation Format">UTF</abbr>-8 (e.g., bytes taken directly from network input), <code>dump()</code> throws <a href=../../../home/exceptions/#jsonexceptiontype_error316><code>type_error.316</code></a> in the default <code>strict</code> mode. To serialize such data without throwing, pass <a href=../error_handler_t/ ><code>error_handler_t::replace</code></a> (substitutes U+FFFD) or <a href=../error_handler_t/ ><code>error_handler_t::ignore</code></a>. Callers that serialize untrusted input on a crash-sensitive path should either choose a non-strict error handler or wrap <code>dump()</code> in a <code class=highlight><span class=k>try</span></code>/<code class=highlight><span class=k>catch</span></code>.</p> <p>See the <a href=../../../home/faq/#serializing-untrusted-or-invalid-utf-8><abbr title="Frequently Asked Questions">FAQ</abbr></a> for details.</p> </div> <h2 id=complexity>Complexity<a class=headerlink href=#complexity title="Permanent link">&para;</a></h2> <p>Linear in the size of the result. With an <code>indent</code>, every line starts with up to <code>indent</code> characters per nesting level, so the result can be larger than the value by a factor of its nesting depth (see <a href=../../../features/parsing/untrusted_input/#nesting-depth>Parsing untrusted input</a>).</p> <h2 id=notes>Notes<a class=headerlink href=#notes title="Permanent link">&para;</a></h2> <p>Floating-point numbers are written with the fewest digits that read back as the same value (for <code class=highlight><span class=kt>double</span></code>; see <a href=../../../features/types/number_handling/#number-Line truncated
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;nlohmann/json.hpp&gt;</span>
<span class=k>using</span><span class=w> </span><span class=n>nlohmann</span><span class=o>::</span><span class=n>json</span><span class=p>;</span>
@@ -105,4 +105,4 @@
<span class=p>[</span><span class=err>jso</span><span class=kc>n</span><span class=err>.excep</span><span class=kc>t</span><span class=err>io</span><span class=kc>n</span><span class=err>.</span><span class=kc>t</span><span class=err>ype_error.</span><span class=mi>316</span><span class=p>]</span><span class=w> </span><span class=err>i</span><span class=kc>n</span><span class=err>valid</span><span class=w> </span><span class=err>UTF</span><span class=mi>-8</span><span class=w> </span><span class=err>by</span><span class=kc>te</span><span class=w> </span><span class=err>a</span><span class=kc>t</span><span class=w> </span><span class=err>i</span><span class=kc>n</span><span class=err>dex</span><span class=w> </span><span class=mi>2</span><span class=p>:</span><span class=w> </span><span class=mi>0</span><span class=err>xA</span><span class=mi>9</span>
<span class=err>s</span><span class=kc>tr</span><span class=err>i</span><span class=kc>n</span><span class=err>g</span><span class=w> </span><span class=err>wi</span><span class=kc>t</span><span class=err>h</span><span class=w> </span><span class=err>replaced</span><span class=w> </span><span class=err>i</span><span class=kc>n</span><span class=err>valid</span><span class=w> </span><span class=err>charac</span><span class=kc>ters</span><span class=p>:</span><span class=w> </span><span class=s2>"ä�ü"</span>
<span class=err>s</span><span class=kc>tr</span><span class=err>i</span><span class=kc>n</span><span class=err>g</span><span class=w> </span><span class=err>wi</span><span class=kc>t</span><span class=err>h</span><span class=w> </span><span class=err>ig</span><span class=kc>n</span><span class=err>ored</span><span class=w> </span><span class=err>i</span><span class=kc>n</span><span class=err>valid</span><span class=w> </span><span class=err>charac</span><span class=kc>ters</span><span class=p>:</span><span class=w> </span><span class=s2>"äü"</span>
</code></pre></div> </details> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li><a href=../to_string/ ><code>to_string</code></a> - returns a string representation of a <abbr title="JavaScript Object Notation">JSON</abbr> value</li> <li><a href=../../operator_ltlt/ ><code>operator&lt;&lt;</code></a> - serialize to stream</li> <li><a href=../../basic_json_view/dump/ ><code>basic_json_view::dump</code></a> - the corresponding function of <code>basic_json_view</code>, serializing directly from a flat index without building a <code>basic_json</code> value</li> <li><a href=../../../features/serialization/ >Serialization</a> - the serialization article</li> </ul> <h2 id=version-history>Version history<a class=headerlink href=#version-history title="Permanent link">&para;</a></h2> <ul> <li>Added in version 1.0.0.</li> <li>Indentation character <code>indent_char</code>, option <code>ensure_ascii</code> and exceptions added in version 3.0.0.</li> <li>Error handlers added in version 3.4.0.</li> <li>Serialization of binary values added in version 3.8.0.</li> <li>Error handler <code>keep</code> added in version 3.13.0 <span class=unreleased-version title="Not part of a release yet; the latest release is 3.12.0.">unreleased</span>.</li> <li>Doubles are written with the shortest digits (Żmij instead of Grisu2) since version 3.13.0 <span class=unreleased-version title="Not part of a release yet; the latest release is 3.12.0.">unreleased</span>; about 0.1% of doubles are written differently, most of them with fewer digits.</li> </ul> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="October 27, 2026 06:41:42 UTC">October 27, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <nav class="md-footer__inner md-grid" aria-label=Footer> <a href=../diff/ class="md-footer__link md-footer__link--prev" aria-label="Previous: diff"> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg> </div> <div class=md-footer__title> <span class=md-footer__direction> Previous </span> <div class=md-ellipsis> diff </div> </div> </a> <a href=../emplace/ class="md-footer__link md-footer__link--next" aria-label="Next: emplace"> <div class=md-footer__title> <span class=md-footer__direction> Next </span> <div class=md-ellipsis> emplace </div> </div> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11z"/></svg> </div> </a> </nav> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> <div class=md-copyright__highlight> Copyright &copy; 2013-2026 Niels Lohmann </div> </div> <div class=md-social> <a href="https://github.com/nlohmann" target="_blank" rel="noopener" title="github.com" class="md-social__link"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 512 512"><!-- Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.Line truncated
</code></pre></div> </details> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li><a href=../to_string/ ><code>to_string</code></a> - returns a string representation of a <abbr title="JavaScript Object Notation">JSON</abbr> value</li> <li><a href=../../operator_ltlt/ ><code>operator&lt;&lt;</code></a> - serialize to stream</li> <li><a href=../../basic_json_view/dump/ ><code>basic_json_view::dump</code></a> - the corresponding function of <code>basic_json_view</code>, serializing directly from a flat index without building a <code>basic_json</code> value</li> <li><a href=../../../features/serialization/ >Serialization</a> - the serialization article</li> </ul> <h2 id=version-history>Version history<a class=headerlink href=#version-history title="Permanent link">&para;</a></h2> <ul> <li>Added in version 1.0.0.</li> <li>Indentation character <code>indent_char</code>, option <code>ensure_ascii</code> and exceptions added in version 3.0.0.</li> <li>Error handlers added in version 3.4.0.</li> <li>Serialization of binary values added in version 3.8.0.</li> <li>Error handler <code>keep</code> added in version 3.13.0 <span class=unreleased-version title="Not part of a release yet; the latest release is 3.12.0.">unreleased</span>.</li> <li>Doubles are written with the shortest digits (Żmij instead of Grisu2) since version 3.13.0 <span class=unreleased-version title="Not part of a release yet; the latest release is 3.12.0.">unreleased</span>; about 0.1% of doubles are written differently, most of them with fewer digits.</li> </ul> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="November 13, 2026 16:54:22 UTC">November 13, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <nav class="md-footer__inner md-grid" aria-label=Footer> <a href=../diff/ class="md-footer__link md-footer__link--prev" aria-label="Previous: diff"> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg> </div> <div class=md-footer__title> <span class=md-footer__direction> Previous </span> <div class=md-ellipsis> diff </div> </div> </a> <a href=../emplace/ class="md-footer__link md-footer__link--next" aria-label="Next: emplace"> <div class=md-footer__title> <span class=md-footer__direction> Next </span> <div class=md-ellipsis> emplace </div> </div> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11z"/></svg> </div> </a> </nav> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> <div class=md-copyright__highlight> Copyright &copy; 2013-2026 Niels Lohmann </div> </div> <div class=md-social> <a href="https://github.com/nlohmann" target="_blank" rel="noopener" title="github.com" class="md-social__link"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 512 512"><!-- Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 1Line truncated
+1 -1
View File
@@ -39,7 +39,7 @@ See the [FAQ](https://json.nlohmann.me/home/faq/#serializing-untrusted-or-invali
## Complexity
Linear.
Linear in the size of the result. With an `indent`, every line starts with up to `indent` characters per nesting level, so the result can be larger than the value by a factor of its nesting depth (see [Parsing untrusted input](https://json.nlohmann.me/features/parsing/untrusted_input/#nesting-depth)).
## Notes
+2 -1
View File
@@ -18,7 +18,8 @@ Strong exception safety: if an exception occurs, the original value stays intact
## Complexity
Linear in the size of the JSON value.
Linear in the size of the result. Every key repeats the path of its value, so the keys can be larger than the value by a
factor of its nesting depth (see [Parsing untrusted input](../../features/parsing/untrusted_input.md#nesting-depth)).
## Notes
+2 -2
View File
@@ -1,5 +1,5 @@
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content="JSON for Modern C++ is a header-only C++11 library that makes JSON a first-class data type."><meta name=author content="Niels Lohmann"><link href="https://json.nlohmann.me/api/basic_json/flatten/" rel="canonical"><link href=../find/ rel=prev><link href=../format_as/ rel=next><link rel=icon href=../../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.8.0"><title>flatten - JSON for Modern C++</title><link rel=stylesheet href=../../../assets/stylesheets/main.57a0d79d.min.css><link rel=stylesheet href=../../../assets/stylesheets/palette.fb2fffe2.min.css><link rel=stylesheet href=../../../css/custom.css><link rel=stylesheet href=../../../css/brand.css><link rel=stylesheet href=../../../css/fig-sax.css><link rel=stylesheet href=../../../css/fig-jsonview.css><link rel=stylesheet href=../../../css/fig-exceptions.css><link rel=stylesheet href=../../../css/fig-pointer.css><link rel=stylesheet href=../../../css/fig-charts.css><link rel=stylesheet href=../../../css/fig-integration.css><link rel=stylesheet href=../../../css/fig-macros.css><script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script></head> <body dir=ltr data-md-color-scheme=default data-md-color-primary=custom data-md-color-accent=custom> <input class=md-toggle data-md-toggle=drawer type=checkbox id=__drawer autocomplete=off> <input class=md-toggle data-md-toggle=search type=checkbox id=__search autocomplete=off> <label class=md-overlay for=__drawer></label> <div data-md-component=skip> <a href=#nlohmannbasic_jsonflatten class=md-skip> Skip to content </a> </div> <div data-md-component=announce> </div> <header class=md-header data-md-component=header> <nav class="md-header__inner md-grid" aria-label=Header> <a href=../../.. title="JSON for Modern C++" class="md-header__button md-logo" aria-label="JSON for Modern C++" data-md-component=logo> <img src=../../../images/wordmark-header.svg alt=logo> </a> <label class="md-header__button md-icon" for=__drawer> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg> </label> <div class=md-header__title data-md-component=header-title> <div class=md-header__ellipsis> <div class=md-header__topic> <span class=md-ellipsis> JSON for Modern C++ </span> </div> <div class=md-header__topic data-md-component=header-topic> <span class=md-ellipsis> flatten </span> </div> </div> </div> <form class=md-header__option data-md-component=palette> <input class=md-option data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme=default data-md-color-primary=custom data-md-color-accent=custom aria-label="Switch to dark mode" type=radio name=__palette id=__palette_0> <label class="md-header__button md-icon" title="Switch to dark mode" for=__palette_1 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> <input class=md-option data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme=slate data-md-color-primary=custom data-md-color-accent=custom aria-label="Switch to light mode" type=radio name=__palette id=__palette_1> <label class="md-header__button md-icon" title="Switch to light mode" for=__palette_0 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> </form> <script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script> <label class="md-header__button md-icon" for=__search> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16Line truncated
</code></pre></div> <p>The function creates a <abbr title="JavaScript Object Notation">JSON</abbr> object whose keys are <abbr title="JavaScript Object Notation">JSON</abbr> pointers (see <a href="https://tools.ietf.org/html/rfc6901"><abbr title="Request for Comments">RFC</abbr> 6901</a>) and whose values are all primitive (see <a href=../is_primitive/ ><code>is_primitive()</code></a> for more information). The original <abbr title="JavaScript Object Notation">JSON</abbr> value can be restored using the <a href=../unflatten/ ><code>unflatten()</code></a> function.</p> <h2 id=return-value>Return value<a class=headerlink href=#return-value title="Permanent link">&para;</a></h2> <p>an object that maps <abbr title="JavaScript Object Notation">JSON</abbr> pointers to primitive values</p> <h2 id=exception-safety>Exception safety<a class=headerlink href=#exception-safety title="Permanent link">&para;</a></h2> <p>Strong exception safety: if an exception occurs, the original value stays intact.</p> <h2 id=complexity>Complexity<a class=headerlink href=#complexity title="Permanent link">&para;</a></h2> <p>Linear in the size of the <abbr title="JavaScript Object Notation">JSON</abbr> value.</p> <h2 id=notes>Notes<a class=headerlink href=#notes title="Permanent link">&para;</a></h2> <p>Empty objects and arrays are flattened to <code class=highlight><span class=kc>null</span></code> and will not be reconstructed correctly by the <a href=../unflatten/ ><code>unflatten()</code></a> function.</p> <h2 id=examples>Examples<a class=headerlink href=#examples title="Permanent link">&para;</a></h2> <details class=example> <summary>Example: flatten a <abbr title="JavaScript Object Notation">JSON</abbr> object</summary> <p>The following code shows how a <abbr title="JavaScript Object Notation">JSON</abbr> object is flattened to an object whose keys consist of <abbr title="JavaScript Object Notation">JSON</abbr> pointers.</p> <div class=highlight><pre><span></span><code><span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;iostream&gt;</span>
</code></pre></div> <p>The function creates a <abbr title="JavaScript Object Notation">JSON</abbr> object whose keys are <abbr title="JavaScript Object Notation">JSON</abbr> pointers (see <a href="https://tools.ietf.org/html/rfc6901"><abbr title="Request for Comments">RFC</abbr> 6901</a>) and whose values are all primitive (see <a href=../is_primitive/ ><code>is_primitive()</code></a> for more information). The original <abbr title="JavaScript Object Notation">JSON</abbr> value can be restored using the <a href=../unflatten/ ><code>unflatten()</code></a> function.</p> <h2 id=return-value>Return value<a class=headerlink href=#return-value title="Permanent link">&para;</a></h2> <p>an object that maps <abbr title="JavaScript Object Notation">JSON</abbr> pointers to primitive values</p> <h2 id=exception-safety>Exception safety<a class=headerlink href=#exception-safety title="Permanent link">&para;</a></h2> <p>Strong exception safety: if an exception occurs, the original value stays intact.</p> <h2 id=complexity>Complexity<a class=headerlink href=#complexity title="Permanent link">&para;</a></h2> <p>Linear in the size of the result. Every key repeats the path of its value, so the keys can be larger than the value by a factor of its nesting depth (see <a href=../../../features/parsing/untrusted_input/#nesting-depth>Parsing untrusted input</a>).</p> <h2 id=notes>Notes<a class=headerlink href=#notes title="Permanent link">&para;</a></h2> <p>Empty objects and arrays are flattened to <code class=highlight><span class=kc>null</span></code> and will not be reconstructed correctly by the <a href=../unflatten/ ><code>unflatten()</code></a> function.</p> <h2 id=examples>Examples<a class=headerlink href=#examples title="Permanent link">&para;</a></h2> <details class=example> <summary>Example: flatten a <abbr title="JavaScript Object Notation">JSON</abbr> object</summary> <p>The following code shows how a <abbr title="JavaScript Object Notation">JSON</abbr> object is flattened to an object whose keys consist of <abbr title="JavaScript Object Notation">JSON</abbr> pointers.</p> <div class=highlight><pre><span></span><code><span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;iostream&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;iomanip&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;nlohmann/json.hpp&gt;</span>
@@ -77,4 +77,4 @@
<span class=w> </span><span class=nt>"empty_object"</span><span class=p>:</span><span class=w> </span><span class=kc>null</span><span class=p>,</span>
<span class=w> </span><span class=nt>"name"</span><span class=p>:</span><span class=w> </span><span class=s2>"Niels"</span>
<span class=p>}</span>
</code></pre></div> </details> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li><a href=../unflatten/ ><code>unflatten</code></a> - the reverse function</li> <li><a href=../../../features/json_pointer/#flatten-unflatten><abbr title="JavaScript Object Notation">JSON</abbr> Pointer</a> - the article on <abbr title="JavaScript Object Notation">JSON</abbr> Pointer and flattening</li> </ul> <h2 id=version-history>Version history<a class=headerlink href=#version-history title="Permanent link">&para;</a></h2> <ul> <li>Added in version 2.0.0.</li> </ul> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="October 27, 2026 06:41:42 UTC">October 27, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <nav class="md-footer__inner md-grid" aria-label=Footer> <a href=../find/ class="md-footer__link md-footer__link--prev" aria-label="Previous: find"> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg> </div> <div class=md-footer__title> <span class=md-footer__direction> Previous </span> <div class=md-ellipsis> find </div> </div> </a> <a href=../format_as/ class="md-footer__link md-footer__link--next" aria-label="Next: format_as"> <div class=md-footer__title> <span class=md-footer__direction> Next </span> <div class=md-ellipsis> format_as </div> </div> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11z"/></svg> </div> </a> </nav> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> <div class=md-copyright__highlight> Copyright &copy; 2013-2026 Niels Lohmann </div> </div> <div class=md-social> <a href="https://github.com/nlohmann" target="_blank" rel="noopener" title="github.com" class="md-social__link"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 512 512"><!-- Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C436.2 457.8 504 362.9 504 252 504 113.3 391.5 8 252.8 8M105.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg> </a> <a href="https://www.linkediLine truncated
</code></pre></div> </details> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li><a href=../unflatten/ ><code>unflatten</code></a> - the reverse function</li> <li><a href=../../../features/json_pointer/#flatten-unflatten><abbr title="JavaScript Object Notation">JSON</abbr> Pointer</a> - the article on <abbr title="JavaScript Object Notation">JSON</abbr> Pointer and flattening</li> </ul> <h2 id=version-history>Version history<a class=headerlink href=#version-history title="Permanent link">&para;</a></h2> <ul> <li>Added in version 2.0.0.</li> </ul> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="November 13, 2026 16:54:22 UTC">November 13, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <nav class="md-footer__inner md-grid" aria-label=Footer> <a href=../find/ class="md-footer__link md-footer__link--prev" aria-label="Previous: find"> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg> </div> <div class=md-footer__title> <span class=md-footer__direction> Previous </span> <div class=md-ellipsis> find </div> </div> </a> <a href=../format_as/ class="md-footer__link md-footer__link--next" aria-label="Next: format_as"> <div class=md-footer__title> <span class=md-footer__direction> Next </span> <div class=md-ellipsis> format_as </div> </div> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11z"/></svg> </div> </a> </nav> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> <div class=md-copyright__highlight> Copyright &copy; 2013-2026 Niels Lohmann </div> </div> <div class=md-social> <a href="https://github.com/nlohmann" target="_blank" rel="noopener" title="github.com" class="md-social__link"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 512 512"><!-- Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C436.2 457.8 504 362.9 504 252 504 113.3 391.5 8 252.8 8M105.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg> </a> <a href="https://www.linkeLine truncated
+1 -1
View File
@@ -16,7 +16,7 @@ Strong exception safety: if an exception occurs, the original value stays intact
## Complexity
Linear in the size of the JSON value.
Linear in the size of the result. Every key repeats the path of its value, so the keys can be larger than the value by a factor of its nesting depth (see [Parsing untrusted input](https://json.nlohmann.me/features/parsing/untrusted_input/#nesting-depth)).
## Notes
+4 -2
View File
@@ -69,8 +69,10 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
## Exceptions
- Throws [parse_error.110](../../home/exceptions.md#jsonexceptionparse_error110) if the given input ends prematurely or
the end of the file was not reached when `strict` was set to true
- Throws [parse_error.110](../../home/exceptions.md#jsonexceptionparse_error110) if the given input ends prematurely,
if the end of the file was not reached when `strict` was set to true, or if a string at the end of the value is not
terminated by 0xFF although a byte follows it (also when `strict` is false: the byte that ends the string is
taken from the input, so the next value would be lost)
- Throws [parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) if a parse error occurs, for instance
an invalid byte, a string that is not valid UTF-8, or an object key that is not a string
+2 -2
View File
@@ -8,7 +8,7 @@
<span class=k>static</span><span class=w> </span><span class=n>basic_json</span><span class=w> </span><span class=n>from_bon8</span><span class=p>(</span><span class=n>IteratorType</span><span class=w> </span><span class=n>first</span><span class=p>,</span><span class=w> </span><span class=n>SentinelType</span><span class=w> </span><span class=n>last</span><span class=p>,</span>
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=n>strict</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=nb>true</span><span class=p>,</span>
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=n>allow_exceptions</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=nb>true</span><span class=p>);</span>
</code></pre></div> <p>Deserializes a given input to a <abbr title="JavaScript Object Notation">JSON</abbr> value using the <abbr title="Binary Object Notation 8">BON8</abbr> (Binary Object Notation 8) serialization format.</p> <ol> <li>Reads from a compatible input.</li> <li>Reads from an iterator range, or an iterator and a sentinel of a different type (C++20 ranges support).</li> </ol> <p>The exact mapping and its limitations are described on a <a href=../../../features/binary_formats/bon8/ >dedicated page</a>.</p> <h2 id=template-parameters>Template parameters<a class=headerlink href=#template-parameters title="Permanent link">&para;</a></h2> <dl> <dt><code>InputType</code></dt> <dd> <p>A compatible input, for instance:</p> <ul> <li>an <code>std::istream</code> object</li> <li>a <code>FILE</code> pointer</li> <li>a C-style array of characters</li> <li>a pointer to a null-terminated string of single byte characters</li> <li>a container <code>obj</code> for which <code>begin(obj)</code> and <code>end(obj)</code> produce a valid pair of iterators (as found via <abbr title="Argument-dependent lookup">ADL</abbr> or member functions, with semantics compatible to <code>std::begin</code> and <code>std::end</code>)</li> </ul> </dd> <dt><code>IteratorType</code></dt> <dd>a compatible iterator type</dd> <dt><code>SentinelType</code></dt> <dd> <p>defaults to <code>IteratorType</code>; may be a different type comparable to <code>IteratorType</code> via <code>operator!=</code>, for instance.</p> <ul> <li>a custom sentinel type for C++20 ranges</li> <li><code>std::default_sentinel_t</code>, when <code>IteratorType</code> is <code>std::counted_iterator</code></li> </ul> </dd> </dl> <h2 id=parameters>Parameters<a class=headerlink href=#parameters title="Permanent link">&para;</a></h2> <dl> <dt><code>i</code> (in)</dt> <dd>an input in <abbr title="Binary Object Notation 8">BON8</abbr> format convertible to an input adapter</dd> <dt><code>first</code> (in)</dt> <dd>iterator to the start of the input</dd> <dt><code>last</code> (in)</dt> <dd>iterator to the end of the input, or a sentinel value that compares equal to the end iterator with <code>operator!=</code></dd> <dt><code>strict</code> (in)</dt> <dd>whether to expect the input to be consumed until <abbr title="End of File">EOF</abbr> (<code class=highlight><span class=nb>true</span></code> by default)</dd> <dt><code>allow_exceptions</code> (in)</dt> <dd>whether to throw exceptions in case of a parse error (optional, <code class=highlight><span class=nb>true</span></code> by default)</dd> </dl> <h2 id=return-value>Return value<a class=headerlink href=#return-value title="Permanent link">&para;</a></h2> <p>deserialized <abbr title="JavaScript Object Notation">JSON</abbr> value; in case of a parse error and <code>allow_exceptions</code> set to <code class=highlight><span class=nb>false</span></code>, the return value will be <code>value_t::discarded</code>. The latter can be checked with <a href=../is_discarded/ ><code>is_discarded</code></a>.</p> <h2 id=exception-safety>Exception safety<a class=headerlink href=#exception-safety title="Permanent link">&para;</a></h2> <p>Strong guarantee: if an exception is thrown, there are no changes in the <abbr title="JavaScript Object Notation">JSON</abbr> value.</p> <h2 id=exceptions>Exceptions<a class=headerlink href=#exceptions title="Permanent link">&para;</a></h2> <ul> <li>Throws <a href=../../../home/exceptions/#jsonexceptionparse_error110>parse_error.110</a> if the given input ends prematurely or the end of the file was not reached when <code>strict</code> was set to true</li> <li>Throws <a href=../../../home/exceptions/#jsonexceptionparse_error112>parse_error.112</a> if a parse error occurs, for instance an invalid byte, a string that is not valid <abbr title="Unicode Transformation Format">UTF</abbr>-8, or an object key that is not a string</li> </ul> <p>The <abbr title="Unicode Transformation Format">UTF</abbr>-8 validity of strings is always checked, independent of <a href=../../macros/json_strict_binary_utf8/ ><code>JSON_STRICT_BINARY_UTF8</code></a>, because the end of a <abbr title="Binary Object Notation 8">BON8</abbr> string is determined from its encoding. Duplicate object keys are accepted; the last value wins (see <a href=../../../features/binary_formats/bon8/ ><abbr title="Binary Object Notation 8">BON8</abbr></a>).</p> <h2 id=complexity>Complexity<a class=headerlink href=#complexity title="Permanent link">&para;</a></h2> <p>Linear in the size of the input.</p> <h2 id=examples>Examples<a class=headerlink href=#examples title="Permanent link">&para;</a></h2> <details class=example> <summary>Example</summary> <p>The example shows the deserialization of a byte vector in <abbr title="Binary Object Notation 8">BON8</abbr> format to a <abbr title="JavaScript Object Notation">JSON</abbr> value.</p> <div class=highlight><pre><span></span><code><span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;iostreaLine truncated
</code></pre></div> <p>Deserializes a given input to a <abbr title="JavaScript Object Notation">JSON</abbr> value using the <abbr title="Binary Object Notation 8">BON8</abbr> (Binary Object Notation 8) serialization format.</p> <ol> <li>Reads from a compatible input.</li> <li>Reads from an iterator range, or an iterator and a sentinel of a different type (C++20 ranges support).</li> </ol> <p>The exact mapping and its limitations are described on a <a href=../../../features/binary_formats/bon8/ >dedicated page</a>.</p> <h2 id=template-parameters>Template parameters<a class=headerlink href=#template-parameters title="Permanent link">&para;</a></h2> <dl> <dt><code>InputType</code></dt> <dd> <p>A compatible input, for instance:</p> <ul> <li>an <code>std::istream</code> object</li> <li>a <code>FILE</code> pointer</li> <li>a C-style array of characters</li> <li>a pointer to a null-terminated string of single byte characters</li> <li>a container <code>obj</code> for which <code>begin(obj)</code> and <code>end(obj)</code> produce a valid pair of iterators (as found via <abbr title="Argument-dependent lookup">ADL</abbr> or member functions, with semantics compatible to <code>std::begin</code> and <code>std::end</code>)</li> </ul> </dd> <dt><code>IteratorType</code></dt> <dd>a compatible iterator type</dd> <dt><code>SentinelType</code></dt> <dd> <p>defaults to <code>IteratorType</code>; may be a different type comparable to <code>IteratorType</code> via <code>operator!=</code>, for instance.</p> <ul> <li>a custom sentinel type for C++20 ranges</li> <li><code>std::default_sentinel_t</code>, when <code>IteratorType</code> is <code>std::counted_iterator</code></li> </ul> </dd> </dl> <h2 id=parameters>Parameters<a class=headerlink href=#parameters title="Permanent link">&para;</a></h2> <dl> <dt><code>i</code> (in)</dt> <dd>an input in <abbr title="Binary Object Notation 8">BON8</abbr> format convertible to an input adapter</dd> <dt><code>first</code> (in)</dt> <dd>iterator to the start of the input</dd> <dt><code>last</code> (in)</dt> <dd>iterator to the end of the input, or a sentinel value that compares equal to the end iterator with <code>operator!=</code></dd> <dt><code>strict</code> (in)</dt> <dd>whether to expect the input to be consumed until <abbr title="End of File">EOF</abbr> (<code class=highlight><span class=nb>true</span></code> by default)</dd> <dt><code>allow_exceptions</code> (in)</dt> <dd>whether to throw exceptions in case of a parse error (optional, <code class=highlight><span class=nb>true</span></code> by default)</dd> </dl> <h2 id=return-value>Return value<a class=headerlink href=#return-value title="Permanent link">&para;</a></h2> <p>deserialized <abbr title="JavaScript Object Notation">JSON</abbr> value; in case of a parse error and <code>allow_exceptions</code> set to <code class=highlight><span class=nb>false</span></code>, the return value will be <code>value_t::discarded</code>. The latter can be checked with <a href=../is_discarded/ ><code>is_discarded</code></a>.</p> <h2 id=exception-safety>Exception safety<a class=headerlink href=#exception-safety title="Permanent link">&para;</a></h2> <p>Strong guarantee: if an exception is thrown, there are no changes in the <abbr title="JavaScript Object Notation">JSON</abbr> value.</p> <h2 id=exceptions>Exceptions<a class=headerlink href=#exceptions title="Permanent link">&para;</a></h2> <ul> <li>Throws <a href=../../../home/exceptions/#jsonexceptionparse_error110>parse_error.110</a> if the given input ends prematurely, if the end of the file was not reached when <code>strict</code> was set to true, or if a string at the end of the value is not terminated by 0xFF although a byte follows it (also when <code>strict</code> is false: the byte that ends the string is taken from the input, so the next value would be lost)</li> <li>Throws <a href=../../../home/exceptions/#jsonexceptionparse_error112>parse_error.112</a> if a parse error occurs, for instance an invalid byte, a string that is not valid <abbr title="Unicode Transformation Format">UTF</abbr>-8, or an object key that is not a string</li> </ul> <p>The <abbr title="Unicode Transformation Format">UTF</abbr>-8 validity of strings is always checked, independent of <a href=../../macros/json_strict_binary_utf8/ ><code>JSON_STRICT_BINARY_UTF8</code></a>, because the end of a <abbr title="Binary Object Notation 8">BON8</abbr> string is determined from its encoding. Duplicate object keys are accepted; the last value wins (see <a href=../../../features/binary_formats/bon8/ ><abbr title="Binary Object Notation 8">BON8</abbr></a>).</p> <h2 id=complexity>Complexity<a class=headerlink href=#complexity title="Permanent link">&para;</a></h2> <p>Linear in the size of the input.</p> <h2 id=examples>Examples<a class=headerlink href=#examples title="Permanent link">&para;</a></h2> <details class=example> <summary>Example</summary> <p>The example shows the deserialization of a byte vector in <abbr title="Binary Object NLine truncated
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;iomanip&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;nlohmann/json.hpp&gt;</span>
@@ -34,4 +34,4 @@
<span class=w> </span><span class=nt>"format"</span><span class=p>:</span><span class=w> </span><span class=s2>"BON8"</span><span class=p>,</span>
<span class=w> </span><span class=nt>"schema"</span><span class=p>:</span><span class=w> </span><span class=mi>0</span>
<span class=p>}</span>
</code></pre></div> </details> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li><a href=../../../features/binary_formats/bon8/ ><abbr title="Binary Object Notation 8">BON8</abbr></a> - the format, its byte layout and how values are mapped</li> <li><a href=../../../features/binary_formats/ >Binary formats</a> - overview and comparison of the supported binary formats</li> <li><a href=../../../features/parsing/untrusted_input/ >Parsing untrusted input</a> - limits and safe handling of hostile data</li> <li><a href=../to_bon8/ ><code>to_bon8</code></a> - create a <abbr title="Binary Object Notation 8">BON8</abbr> serialization of a <abbr title="JavaScript Object Notation">JSON</abbr> value</li> <li><a href=../from_cbor/ ><code>from_cbor</code></a> - create a <abbr title="JavaScript Object Notation">JSON</abbr> value from an input in <abbr title="Concise Binary Object Representation">CBOR</abbr> format</li> <li><a href=../from_msgpack/ ><code>from_msgpack</code></a> - create a <abbr title="JavaScript Object Notation">JSON</abbr> value from an input in MessagePack format</li> <li><a href=../from_bson/ ><code>from_bson</code></a> - create a <abbr title="JavaScript Object Notation">JSON</abbr> value from an input in <abbr title="Binary JSON">BSON</abbr> format</li> <li><a href=../from_ubjson/ ><code>from_ubjson</code></a> - create a <abbr title="JavaScript Object Notation">JSON</abbr> value from an input in <abbr title="Universal Binary JSON">UBJSON</abbr> format</li> <li><a href=../from_bjdata/ ><code>from_bjdata</code></a> - create a <abbr title="JavaScript Object Notation">JSON</abbr> value from an input in <abbr title="Binary JData">BJData</abbr> format</li> </ul> <h2 id=version-history>Version history<a class=headerlink href=#version-history title="Permanent link">&para;</a></h2> <ul> <li>Added in version 3.13.0 <span class=unreleased-version title="Not part of a release yet; the latest release is 3.12.0.">unreleased</span>.</li> </ul> <div class="admonition warning"> <p class=admonition-title>Deprecation</p> <ul> <li>Overload (2) replaces calls to <code>from_bon8</code> with a pointer and a length as first two parameters, which has been deprecated in version 3.13.0 <span class=unreleased-version title="Not part of a release yet; the latest release is 3.12.0.">unreleased</span>. In version 4.0.0 <span class=unreleased-version title="Not part of a release yet; the latest release is 3.12.0.">unreleased</span>, this overload will be deleted (<code>= delete</code>) rather than removed. Please replace all calls like <code class=highlight><span class=n>from_bon8</span><span class=p>(</span><span class=n>ptr</span><span class=p>,</span><span class=w> </span><span class=n>len</span><span class=p>,</span><span class=w> </span><span class=p>...);</span></code> with <code class=highlight><span class=n>from_bon8</span><span class=p>(</span><span class=n>ptr</span><span class=p>,</span><span class=w> </span><span class=n>ptr</span><span class=o>+</span><span class=n>len</span><span class=p>,</span><span class=w> </span><span class=p>...);</span></code>.</li> </ul> <p>You should be warned by your compiler with a <code>-Wdeprecated-declarations</code> warning if you are using a deprecated function.</p> </div> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="October 27, 2026 06:41:42 UTC">October 27, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <nav class="md-footer__inner md-grid" aria-label=Footer> <a href=../from_bjdata/ class="md-footer__link md-footer__link--prev" ariaLine truncated
</code></pre></div> </details> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li><a href=../../../features/binary_formats/bon8/ ><abbr title="Binary Object Notation 8">BON8</abbr></a> - the format, its byte layout and how values are mapped</li> <li><a href=../../../features/binary_formats/ >Binary formats</a> - overview and comparison of the supported binary formats</li> <li><a href=../../../features/parsing/untrusted_input/ >Parsing untrusted input</a> - limits and safe handling of hostile data</li> <li><a href=../to_bon8/ ><code>to_bon8</code></a> - create a <abbr title="Binary Object Notation 8">BON8</abbr> serialization of a <abbr title="JavaScript Object Notation">JSON</abbr> value</li> <li><a href=../from_cbor/ ><code>from_cbor</code></a> - create a <abbr title="JavaScript Object Notation">JSON</abbr> value from an input in <abbr title="Concise Binary Object Representation">CBOR</abbr> format</li> <li><a href=../from_msgpack/ ><code>from_msgpack</code></a> - create a <abbr title="JavaScript Object Notation">JSON</abbr> value from an input in MessagePack format</li> <li><a href=../from_bson/ ><code>from_bson</code></a> - create a <abbr title="JavaScript Object Notation">JSON</abbr> value from an input in <abbr title="Binary JSON">BSON</abbr> format</li> <li><a href=../from_ubjson/ ><code>from_ubjson</code></a> - create a <abbr title="JavaScript Object Notation">JSON</abbr> value from an input in <abbr title="Universal Binary JSON">UBJSON</abbr> format</li> <li><a href=../from_bjdata/ ><code>from_bjdata</code></a> - create a <abbr title="JavaScript Object Notation">JSON</abbr> value from an input in <abbr title="Binary JData">BJData</abbr> format</li> </ul> <h2 id=version-history>Version history<a class=headerlink href=#version-history title="Permanent link">&para;</a></h2> <ul> <li>Added in version 3.13.0 <span class=unreleased-version title="Not part of a release yet; the latest release is 3.12.0.">unreleased</span>.</li> </ul> <div class="admonition warning"> <p class=admonition-title>Deprecation</p> <ul> <li>Overload (2) replaces calls to <code>from_bon8</code> with a pointer and a length as first two parameters, which has been deprecated in version 3.13.0 <span class=unreleased-version title="Not part of a release yet; the latest release is 3.12.0.">unreleased</span>. In version 4.0.0 <span class=unreleased-version title="Not part of a release yet; the latest release is 3.12.0.">unreleased</span>, this overload will be deleted (<code>= delete</code>) rather than removed. Please replace all calls like <code class=highlight><span class=n>from_bon8</span><span class=p>(</span><span class=n>ptr</span><span class=p>,</span><span class=w> </span><span class=n>len</span><span class=p>,</span><span class=w> </span><span class=p>...);</span></code> with <code class=highlight><span class=n>from_bon8</span><span class=p>(</span><span class=n>ptr</span><span class=p>,</span><span class=w> </span><span class=n>ptr</span><span class=o>+</span><span class=n>len</span><span class=p>,</span><span class=w> </span><span class=p>...);</span></code>.</li> </ul> <p>You should be warned by your compiler with a <code>-Wdeprecated-declarations</code> warning if you are using a deprecated function.</p> </div> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="November 13, 2026 16:54:30 UTC">November 13, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <nav class="md-footer__inner md-grid" aria-label=Footer> <a href=../from_bjdata/ class="md-footer__link md-footer__link--prev" arLine truncated
+1 -1
View File
@@ -64,7 +64,7 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
## Exceptions
- Throws [parse_error.110](https://json.nlohmann.me/home/exceptions/#jsonexceptionparse_error110) if the given input ends prematurely or the end of the file was not reached when `strict` was set to true
- Throws [parse_error.110](https://json.nlohmann.me/home/exceptions/#jsonexceptionparse_error110) if the given input ends prematurely, if the end of the file was not reached when `strict` was set to true, or if a string at the end of the value is not terminated by 0xFF although a byte follows it (also when `strict` is false: the byte that ends the string is taken from the input, so the next value would be lost)
- Throws [parse_error.112](https://json.nlohmann.me/home/exceptions/#jsonexceptionparse_error112) if a parse error occurs, for instance an invalid byte, a string that is not valid UTF-8, or an object key that is not a string
The UTF-8 validity of strings is always checked, independent of [`JSON_STRICT_BINARY_UTF8`](https://json.nlohmann.me/api/macros/json_strict_binary_utf8/index.md), because the end of a BON8 string is determined from its encoding. Duplicate object keys are accepted; the last value wins (see [BON8](https://json.nlohmann.me/features/binary_formats/bon8/index.md)).
+15 -14
View File
@@ -27,7 +27,7 @@ comparison of two [`json_view`](../basic_json_view/index.md) documents has a fix
and does not depend on it either.
The call stack that these operations need grows with the limit: roughly *a few kilobytes plus a cost per level times the
limit*, where the cost per level is up to about 2.3 KiB in an unoptimized and up to about 0.5 KiB in an optimized build
limit*, where the cost per level is up to about 1.8 KiB in an unoptimized and up to about 0.5 KiB in an optimized build
(see [Stack needed](#stack-needed)). The default of `128` levels is tuned for threads with ordinary stacks of a few
hundred kilobytes or more. Set a lower limit if your threads have small stacks (RTOS tasks, fibers, threads of the musl
C
@@ -67,7 +67,7 @@ When the macro is not defined, the library defines it to its default value.
the levels that are descended into are counted, so the count never exceeds the limit, not even when user code (a
copy constructor of a custom base class, say) copies a value while a copy is going on. A byte holds `255` at
most, and the limit stays below that, so that the count cannot wrap around. (More levels would hardly be
useful: `254` levels need up to 576 KiB of stack in an unoptimized build already, twice as much as the
useful: `254` levels need up to 448 KiB of stack in an unoptimized build already, twice as much as the
default.)
### Stack needed
@@ -83,7 +83,7 @@ Unoptimized (`-O0`):
| Operation | limit 16 | limit 32 | limit 64 | limit 128 | limit 254 |
|---|---:|---:|---:|---:|---:|
| `dump()` and `dump(indent)`, `operator<<` | 48 / 32 | 80 / 64 | 144 / 128 | 288 / 256 | 576 / 512 |
| `dump()` and `dump(indent)`, `operator<<` | 16 / 16 | 16 / 16 | 32 / 32 | 48 / 48 | 96 / 96 |
| copy construction and assignment | 32 / 16 | 48 / 32 | 112 / 80 | 224 / 144 | 432 / 304 |
| `==` | 16 / 16 | 16 / 16 | 16 / 16 | 48 / 32 | 96 / 48 |
| `<=>` (C++20) | 16 / 16 | 16 / 16 | 32 / 32 | 64 / 64 | 144 / 128 |
@@ -123,23 +123,24 @@ The rule of thumb is
> stack needed ≈ a few KiB + cost per level × limit
with a cost per level of up to 2.3 KiB (`dump` at `-O0` with Clang; 2.1 KiB with GCC), 1.7 KiB for copying and merging
(1.3 KiB with GCC), and 0.1 to 0.5 KiB for most other operations at `-O0`; and 0.5 KiB or less at `-O2`. The numbers
come from the difference between the limits `128` and `254` in the tables, so they are rough: other compilers,
other targets (the frames of x86-64 code are about as large), other standard libraries, `JSON_DIAGNOSTICS`, and
sanitizers change them. Measure with your own tool chain (see the example below) rather than relying on the tables.
The stack that your own code and the operating system need comes on top of these numbers.
with a cost per level of up to 1.8 KiB (conversion to another `basic_json` type at `-O0` with Clang; 1.3 KiB with
GCC), 1.7 KiB for copying and merging (1.3 KiB with GCC), 0.4 KiB for `dump`, and 0.1 to 0.5 KiB for most other
operations at `-O0`; and 0.5 KiB or less at `-O2`. The numbers come from the difference between the limits `128` and
`254` in the tables, so they are rough: other compilers, other targets (the frames of x86-64 code are about as large),
other standard libraries, `JSON_DIAGNOSTICS`, and sanitizers change them. Measure with your own tool chain (see the
example below) rather than relying on the tables. The stack that your own code and the operating system need comes on
top of these numbers.
Which limit to choose, for the stack that you can spare for the library (the largest limit of those measured
for which the slowest operation needs at most that much):
| Stack for the library | optimized (`-O2`) | unoptimized (`-O0`) |
|---|---:|---:|
| 32 KiB | 64 | 0 |
| 64 KiB | 128 | 16 |
| 128 KiB (the default stack of threads on musl) | 254 | 32 |
| 256 KiB | 254 | 64 |
| 512 KiB | 254 | 128 |
| 32 KiB | 64 | 16 |
| 64 KiB | 128 | 32 |
| 128 KiB (the default stack of threads on musl) | 254 | 64 |
| 256 KiB | 254 | 128 |
| 512 KiB | 254 | 254 |
| 1 MiB or more | 254 | 254 |
### Speed
@@ -1,6 +1,6 @@
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content="JSON for Modern C++ is a header-only C++11 library that makes JSON a first-class data type."><meta name=author content="Niels Lohmann"><link href="https://json.nlohmann.me/api/macros/json_recursion_depth_limit/" rel="canonical"><link href=../json_precise_stream_position/ rel=prev><link href=../json_skip_library_version_check/ rel=next><link rel=icon href=../../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.8.0"><title>JSON_RECURSION_DEPTH_LIMIT - JSON for Modern C++</title><link rel=stylesheet href=../../../assets/stylesheets/main.57a0d79d.min.css><link rel=stylesheet href=../../../assets/stylesheets/palette.fb2fffe2.min.css><link rel=stylesheet href=../../../css/custom.css><link rel=stylesheet href=../../../css/brand.css><link rel=stylesheet href=../../../css/fig-sax.css><link rel=stylesheet href=../../../css/fig-jsonview.css><link rel=stylesheet href=../../../css/fig-exceptions.css><link rel=stylesheet href=../../../css/fig-pointer.css><link rel=stylesheet href=../../../css/fig-charts.css><link rel=stylesheet href=../../../css/fig-integration.css><link rel=stylesheet href=../../../css/fig-macros.css><script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script></head> <body dir=ltr data-md-color-scheme=default data-md-color-primary=custom data-md-color-accent=custom> <input class=md-toggle data-md-toggle=drawer type=checkbox id=__drawer autocomplete=off> <input class=md-toggle data-md-toggle=search type=checkbox id=__search autocomplete=off> <label class=md-overlay for=__drawer></label> <div data-md-component=skip> <a href=#json_recursion_depth_limit class=md-skip> Skip to content </a> </div> <div data-md-component=announce> </div> <header class=md-header data-md-component=header> <nav class="md-header__inner md-grid" aria-label=Header> <a href=../../.. title="JSON for Modern C++" class="md-header__button md-logo" aria-label="JSON for Modern C++" data-md-component=logo> <img src=../../../images/wordmark-header.svg alt=logo> </a> <label class="md-header__button md-icon" for=__drawer> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg> </label> <div class=md-header__title data-md-component=header-title> <div class=md-header__ellipsis> <div class=md-header__topic> <span class=md-ellipsis> JSON for Modern C++ </span> </div> <div class=md-header__topic data-md-component=header-topic> <span class=md-ellipsis> JSON_RECURSION_DEPTH_LIMIT </span> </div> </div> </div> <form class=md-header__option data-md-component=palette> <input class=md-option data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme=default data-md-color-primary=custom data-md-color-accent=custom aria-label="Switch to dark mode" type=radio name=__palette id=__palette_0> <label class="md-header__button md-icon" title="Switch to dark mode" for=__palette_1 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> <input class=md-option data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme=slate data-md-color-primary=custom data-md-color-accent=custom aria-label="Switch to light mode" type=radio name=__palette id=__palette_1> <label class="md-header__button md-icon" title="Switch to light mode" for=__palette_0 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> </form> <script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script> <label class="md-header__button md-icon" for=Line truncated
</code></pre></div> <p>This macro sets how many nesting levels the operations that walk a value recurse into on the call stack. Beyond that, they continue with an explicit stack on the heap. The value is an integer constant from <code>0</code> to <code>254</code>; the default is <code>128</code>.</p> <p>The operations are copying a value, comparing two values, serializing with <a href=../../basic_json/dump/ ><code>dump</code></a> or <a href=../../operator_ltlt/ ><code>operator&lt;&lt;</code></a>, hashing with <code>std::hash</code>, <a href=../../basic_json/merge_patch/ ><code>merge_patch</code></a>, <a href=../../basic_json/update/ ><code>update</code></a> with <code>merge_objects</code>, <a href=../../basic_json/diff/ ><code>diff</code></a>, <a href=../../basic_json/merge_diff/ ><code>merge_diff</code></a>, converting a value to another specialization of <code>basic_json</code>, destroying a value, and the binary writers <a href=../../basic_json/to_cbor/ ><code>to_cbor</code></a>, <a href=../../basic_json/to_msgpack/ ><code>to_msgpack</code></a>, <a href=../../basic_json/to_ubjson/ ><code>to_ubjson</code></a>, <a href=../../basic_json/to_bjdata/ ><code>to_bjdata</code></a>, and <a href=../../basic_json/to_bon8/ ><code>to_bon8</code></a>. They share this one limit; none has a limit of its own. Recursing is the fastest way to walk a value, but a value nested deeply enough would exhaust the call stack, so the library recurses only as far as the limit and finishes the levels below with an explicit stack. This is what makes all of them safe for untrusted input (see <a href=../../../features/parsing/untrusted_input/#nesting-depth>Nesting depth</a>). Parsing, the binary readers, <a href=../../basic_json/flatten/ ><code>flatten</code></a>, <a href=../../basic_json/unflatten/ ><code>unflatten</code></a>, and <a href=../../basic_json/to_bson/ ><code>to_bson</code></a> always use an explicit stack and do not depend on the macro. The lockstep comparison of two <a href=../../basic_json_view/ ><code>json_view</code></a> documents has a fixed bound of its own, 48 levels, and does not depend on it either.</p> <p>The call stack that these operations need grows with the limit: roughly <em>a few kilobytes plus a cost per level times the limit</em>, where the cost per level is up to about 2.3 KiB in an unoptimized and up to about 0.5 KiB in an optimized build (see <a href=#stack-needed>Stack needed</a>). The default of <code>128</code> levels is tuned for threads with ordinary stacks of a few hundred kilobytes or more. Set a lower limit if your threads have small stacks (RTOS tasks, fibers, threads of the musl C library, which has a default stack of 128 KiB), or a higher limit to trade stack for speed on deeply nested values.</p> <p>The macro changes only how much stack is used and how fast the operations are. It never changes a result: every operation returns the same value for every setting of the limit, for values nested less deeply than the limit as well as for values nested more deeply.</p> <h2 id=default-definition>Default definition<a class=headerlink href=#default-definition title="Permanent link">&para;</a></h2> <p>The default value is <code>128</code>.</p> <div class=highlight><pre><span></span><code><span class=cp>#define JSON_RECURSION_DEPTH_LIMIT 128</span>
</code></pre></div> <p>When the macro is not defined, the library defines it to its default value.</p> <h2 id=notes>Notes<a class=headerlink href=#notes title="Permanent link">&para;</a></h2> <div class="admonition note"> <p class=admonition-title>Allowed values</p> <p>The value must be an integer constant expression from <code>0</code> to <code>254</code>; any other value (a negative number, a number above <code>254</code>, a floating-point number such as <code>254.0</code>, or <code>true</code> or <code>false</code>) is rejected at compile time with an error message that names the macro. A character of any character type (<code>'a'</code>, <code>L'a'</code>, <code>u8'a'</code>, ...) is rejected, too, although it is an integer.</p> <ul> <li><code>0</code> is allowed, and means that every operation uses its explicit stack from the first level on and no operation recurses over the nesting of a value at all. That needs a constant amount of call stack (at most 16 KiB in the measurements below, for a value nested 20,000 levels deep) and is the setting for tiny stacks, at the price of speed (see <a href=#speed>Speed</a>).</li> <li><code>254</code> is the largest allowed value. Copying a value and comparing two values (with <code>&lt;=&gt;</code>, or with the operators on objects and arrays of a custom type) cannot pass the depth down as an argument, because the signatures of the copy constructor and the operators are fixed. They count the levels they have descended into in a variable of type <code class=highlight><span class=n>std</span><span class=o>::</span><span class=kt>uint8_t</span></code> that exists once per thread (see <a href=../json_no_thread_local/ ><code>JSON_NO_THREAD_LOCAL</code></a>). Only the levels that are descended into are counted, so the count never exceeds the limit, not even when user code (a copy constructor of a custom base class, say) copies a value while a copy is going on. A byte holds <code>255</code> at most, and the limit stays below that, so that the count cannot wrap around. (More levels would hardly be useful: <code>254</code> levels need up to 576 KiB of stack in an unoptimized build already, twice as much as the default.)</li> </ul> </div> <h3 id=stack-needed>Stack needed<a class=headerlink href=#stack-needed title="Permanent link">&para;</a></h3> <p>The tables show the smallest stack that an operation needs, in KiB, at several limits, on a value that is nested more deeply than the limit (limit + 10 levels). Each cell shows the result for Clang (Apple clang 21) and for <abbr title="GNU Compiler Collection">GCC</abbr> 16, separated by a slash; both measured on macOS with arm64, compiling in C++20 mode. The operations run in a thread whose stack has the size given, and are not given any stack that they do not need: the value is built, and the result destroyed, outside of that thread. Stacks can only be set in steps of 16 KiB (the page size), so <code>16</code> means "16 KiB or less". A row stands for all operations listed; the table shows the largest value among them.</p> <p>Unoptimized (<code>-O0</code>):</p> <table> <thead> <tr> <th>Operation</th> <th style="text-align: right;">limit 16</th> <th style="text-align: right;">limit 32</th> <th style="text-align: right;">limit 64</th> <th style="text-align: right;">limit 128</th> <th style="text-align: right;">limit 254</th> </tr> </thead> <tbody> <tr> <td><code>dump()</code> and <code>dump(indent)</code>, <code>operator&lt;&lt;</code></td> <td style="text-align: right;">48 / 32</td> <td style="text-align: right;">80 / 64</td> <td style="text-align: right;">144 / 128</td> <td style="text-align: right;">288 / 256</td> <td style="text-align: right;">576 / 512</td> </tr> <tr> <td>copy construction and assignment</td> <td style="text-align: right;">32 / 16</td> <td style="text-align: right;">48 / 32</td> <td style="text-align: right;">112 / 80</td> <td style="text-align: right;">224 / 144</td> <td style="text-align: right;">432 / 304</td> </tr> <tr> <td><code>==</code></td> <td style="text-align: right;">16 / 16</td> <td style="text-align: right;">16 / 16</td> <td style="text-align: right;">16 / 16</td> <td style="text-align: right;">48 / 32</td> <td style="text-align: right;">96 / 48</td> </tr> <tr> <td><code>&lt;=&gt;</code> (C++20)</td> <td style="text-align: right;">16 / 16</td> <td style="text-align: right;">16 / 16</td> <td style="text-align: right;">32 / 32</td> <td style="text-align: right;">64 / 64</td> <td style="text-align: right;">144 / 128</td> </tr> <tr> <td><code>std::hash</code></td> <td style="text-align: right;">16 / 16</td> <td style="text-align: right;">16 / 16</td> <td style="text-align: right;">32 / 32</td> <td style="text-align: right;">80 / 64</td> <td style="text-align: right;">160 / 128</td> </tr> <tr> <td><code>merge_patch</code>, <code>update(j, true)</code>, <code>patch</code></td> <td style="text-align: right;">32 / 16</td> <td style="text-align: right;">48 / 32</td> <td style="text-align: right;">112 / Line truncated
</code></pre></div> <p>This macro sets how many nesting levels the operations that walk a value recurse into on the call stack. Beyond that, they continue with an explicit stack on the heap. The value is an integer constant from <code>0</code> to <code>254</code>; the default is <code>128</code>.</p> <p>The operations are copying a value, comparing two values, serializing with <a href=../../basic_json/dump/ ><code>dump</code></a> or <a href=../../operator_ltlt/ ><code>operator&lt;&lt;</code></a>, hashing with <code>std::hash</code>, <a href=../../basic_json/merge_patch/ ><code>merge_patch</code></a>, <a href=../../basic_json/update/ ><code>update</code></a> with <code>merge_objects</code>, <a href=../../basic_json/diff/ ><code>diff</code></a>, <a href=../../basic_json/merge_diff/ ><code>merge_diff</code></a>, converting a value to another specialization of <code>basic_json</code>, destroying a value, and the binary writers <a href=../../basic_json/to_cbor/ ><code>to_cbor</code></a>, <a href=../../basic_json/to_msgpack/ ><code>to_msgpack</code></a>, <a href=../../basic_json/to_ubjson/ ><code>to_ubjson</code></a>, <a href=../../basic_json/to_bjdata/ ><code>to_bjdata</code></a>, and <a href=../../basic_json/to_bon8/ ><code>to_bon8</code></a>. They share this one limit; none has a limit of its own. Recursing is the fastest way to walk a value, but a value nested deeply enough would exhaust the call stack, so the library recurses only as far as the limit and finishes the levels below with an explicit stack. This is what makes all of them safe for untrusted input (see <a href=../../../features/parsing/untrusted_input/#nesting-depth>Nesting depth</a>). Parsing, the binary readers, <a href=../../basic_json/flatten/ ><code>flatten</code></a>, <a href=../../basic_json/unflatten/ ><code>unflatten</code></a>, and <a href=../../basic_json/to_bson/ ><code>to_bson</code></a> always use an explicit stack and do not depend on the macro. The lockstep comparison of two <a href=../../basic_json_view/ ><code>json_view</code></a> documents has a fixed bound of its own, 48 levels, and does not depend on it either.</p> <p>The call stack that these operations need grows with the limit: roughly <em>a few kilobytes plus a cost per level times the limit</em>, where the cost per level is up to about 1.8 KiB in an unoptimized and up to about 0.5 KiB in an optimized build (see <a href=#stack-needed>Stack needed</a>). The default of <code>128</code> levels is tuned for threads with ordinary stacks of a few hundred kilobytes or more. Set a lower limit if your threads have small stacks (RTOS tasks, fibers, threads of the musl C library, which has a default stack of 128 KiB), or a higher limit to trade stack for speed on deeply nested values.</p> <p>The macro changes only how much stack is used and how fast the operations are. It never changes a result: every operation returns the same value for every setting of the limit, for values nested less deeply than the limit as well as for values nested more deeply.</p> <h2 id=default-definition>Default definition<a class=headerlink href=#default-definition title="Permanent link">&para;</a></h2> <p>The default value is <code>128</code>.</p> <div class=highlight><pre><span></span><code><span class=cp>#define JSON_RECURSION_DEPTH_LIMIT 128</span>
</code></pre></div> <p>When the macro is not defined, the library defines it to its default value.</p> <h2 id=notes>Notes<a class=headerlink href=#notes title="Permanent link">&para;</a></h2> <div class="admonition note"> <p class=admonition-title>Allowed values</p> <p>The value must be an integer constant expression from <code>0</code> to <code>254</code>; any other value (a negative number, a number above <code>254</code>, a floating-point number such as <code>254.0</code>, or <code>true</code> or <code>false</code>) is rejected at compile time with an error message that names the macro. A character of any character type (<code>'a'</code>, <code>L'a'</code>, <code>u8'a'</code>, ...) is rejected, too, although it is an integer.</p> <ul> <li><code>0</code> is allowed, and means that every operation uses its explicit stack from the first level on and no operation recurses over the nesting of a value at all. That needs a constant amount of call stack (at most 16 KiB in the measurements below, for a value nested 20,000 levels deep) and is the setting for tiny stacks, at the price of speed (see <a href=#speed>Speed</a>).</li> <li><code>254</code> is the largest allowed value. Copying a value and comparing two values (with <code>&lt;=&gt;</code>, or with the operators on objects and arrays of a custom type) cannot pass the depth down as an argument, because the signatures of the copy constructor and the operators are fixed. They count the levels they have descended into in a variable of type <code class=highlight><span class=n>std</span><span class=o>::</span><span class=kt>uint8_t</span></code> that exists once per thread (see <a href=../json_no_thread_local/ ><code>JSON_NO_THREAD_LOCAL</code></a>). Only the levels that are descended into are counted, so the count never exceeds the limit, not even when user code (a copy constructor of a custom base class, say) copies a value while a copy is going on. A byte holds <code>255</code> at most, and the limit stays below that, so that the count cannot wrap around. (More levels would hardly be useful: <code>254</code> levels need up to 448 KiB of stack in an unoptimized build already, twice as much as the default.)</li> </ul> </div> <h3 id=stack-needed>Stack needed<a class=headerlink href=#stack-needed title="Permanent link">&para;</a></h3> <p>The tables show the smallest stack that an operation needs, in KiB, at several limits, on a value that is nested more deeply than the limit (limit + 10 levels). Each cell shows the result for Clang (Apple clang 21) and for <abbr title="GNU Compiler Collection">GCC</abbr> 16, separated by a slash; both measured on macOS with arm64, compiling in C++20 mode. The operations run in a thread whose stack has the size given, and are not given any stack that they do not need: the value is built, and the result destroyed, outside of that thread. Stacks can only be set in steps of 16 KiB (the page size), so <code>16</code> means "16 KiB or less". A row stands for all operations listed; the table shows the largest value among them.</p> <p>Unoptimized (<code>-O0</code>):</p> <table> <thead> <tr> <th>Operation</th> <th style="text-align: right;">limit 16</th> <th style="text-align: right;">limit 32</th> <th style="text-align: right;">limit 64</th> <th style="text-align: right;">limit 128</th> <th style="text-align: right;">limit 254</th> </tr> </thead> <tbody> <tr> <td><code>dump()</code> and <code>dump(indent)</code>, <code>operator&lt;&lt;</code></td> <td style="text-align: right;">16 / 16</td> <td style="text-align: right;">16 / 16</td> <td style="text-align: right;">32 / 32</td> <td style="text-align: right;">48 / 48</td> <td style="text-align: right;">96 / 96</td> </tr> <tr> <td>copy construction and assignment</td> <td style="text-align: right;">32 / 16</td> <td style="text-align: right;">48 / 32</td> <td style="text-align: right;">112 / 80</td> <td style="text-align: right;">224 / 144</td> <td style="text-align: right;">432 / 304</td> </tr> <tr> <td><code>==</code></td> <td style="text-align: right;">16 / 16</td> <td style="text-align: right;">16 / 16</td> <td style="text-align: right;">16 / 16</td> <td style="text-align: right;">48 / 32</td> <td style="text-align: right;">96 / 48</td> </tr> <tr> <td><code>&lt;=&gt;</code> (C++20)</td> <td style="text-align: right;">16 / 16</td> <td style="text-align: right;">16 / 16</td> <td style="text-align: right;">32 / 32</td> <td style="text-align: right;">64 / 64</td> <td style="text-align: right;">144 / 128</td> </tr> <tr> <td><code>std::hash</code></td> <td style="text-align: right;">16 / 16</td> <td style="text-align: right;">16 / 16</td> <td style="text-align: right;">32 / 32</td> <td style="text-align: right;">80 / 64</td> <td style="text-align: right;">160 / 128</td> </tr> <tr> <td><code>merge_patch</code>, <code>update(j, true)</code>, <code>patch</code></td> <td style="text-align: right;">32 / 16</td> <td style="text-align: right;">48 / 32</td> <td style="text-align: right;">112 / 80</tdLine truncated
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;iostream&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;utility&gt;</span>
@@ -69,4 +69,4 @@ same hash: true
<span class=w> </span><span class=n>pthread_create</span><span class=p>(</span><span class=o>&amp;</span><span class=kr>thread</span><span class=p>,</span><span class=w> </span><span class=o>&amp;</span><span class=n>attr</span><span class=p>,</span><span class=w> </span><span class=n>run</span><span class=p>,</span><span class=w> </span><span class=nb>nullptr</span><span class=p>);</span>
<span class=w> </span><span class=n>pthread_join</span><span class=p>(</span><span class=kr>thread</span><span class=p>,</span><span class=w> </span><span class=nb>nullptr</span><span class=p>);</span>
<span class=p>}</span>
</code></pre></div> </details> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li><a href=../../../features/parsing/untrusted_input/#nesting-depth>Nesting depth</a> - how the library handles deeply nested values</li> <li><a href=../json_no_thread_local/ ><code>JSON_NO_THREAD_LOCAL</code></a> - switch off the use of <code>thread_local</code> storage</li> <li><a href=../../../features/macros/ >Supported Macros</a> - guide to all supported macros</li> </ul> <h2 id=version-history>Version history<a class=headerlink href=#version-history title="Permanent link">&para;</a></h2> <ul> <li>Added in version 3.13.0 <span class=unreleased-version title="Not part of a release yet; the latest release is 3.12.0.">unreleased</span>.</li> </ul> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="November 11, 2026 21:32:05 UTC">November 11, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <nav class="md-footer__inner md-grid" aria-label=Footer> <a href=../json_precise_stream_position/ class="md-footer__link md-footer__link--prev" aria-label="Previous: JSON_PRECISE_STREAM_POSITION"> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg> </div> <div class=md-footer__title> <span class=md-footer__direction> Previous </span> <div class=md-ellipsis> JSON_PRECISE_STREAM_POSITION </div> </div> </a> <a href=../json_skip_library_version_check/ class="md-footer__link md-footer__link--next" aria-label="Next: JSON_SKIP_LIBRARY_VERSION_CHECK"> <div class=md-footer__title> <span class=md-footer__direction> Next </span> <div class=md-ellipsis> JSON_SKIP_LIBRARY_VERSION_CHECK </div> </div> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11z"/></svg> </div> </a> </nav> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> <div class=md-copyright__highlight> Copyright &copy; 2013-2026 Niels Lohmann </div> </div> <div class=md-social> <a href="https://github.com/nlohmann" target="_blank" rel="noopener" title="github.com" class="md-social__link"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 512 512"><!-- Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C436.2 457.8 504 362.9 504 252 504 113.3 391.5 8 252.8 8M105.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-Line truncated
</code></pre></div> </details> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li><a href=../../../features/parsing/untrusted_input/#nesting-depth>Nesting depth</a> - how the library handles deeply nested values</li> <li><a href=../json_no_thread_local/ ><code>JSON_NO_THREAD_LOCAL</code></a> - switch off the use of <code>thread_local</code> storage</li> <li><a href=../../../features/macros/ >Supported Macros</a> - guide to all supported macros</li> </ul> <h2 id=version-history>Version history<a class=headerlink href=#version-history title="Permanent link">&para;</a></h2> <ul> <li>Added in version 3.13.0 <span class=unreleased-version title="Not part of a release yet; the latest release is 3.12.0.">unreleased</span>.</li> </ul> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="November 13, 2026 16:54:11 UTC">November 13, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <nav class="md-footer__inner md-grid" aria-label=Footer> <a href=../json_precise_stream_position/ class="md-footer__link md-footer__link--prev" aria-label="Previous: JSON_PRECISE_STREAM_POSITION"> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg> </div> <div class=md-footer__title> <span class=md-footer__direction> Previous </span> <div class=md-ellipsis> JSON_PRECISE_STREAM_POSITION </div> </div> </a> <a href=../json_skip_library_version_check/ class="md-footer__link md-footer__link--next" aria-label="Next: JSON_SKIP_LIBRARY_VERSION_CHECK"> <div class=md-footer__title> <span class=md-footer__direction> Next </span> <div class=md-ellipsis> JSON_SKIP_LIBRARY_VERSION_CHECK </div> </div> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11z"/></svg> </div> </a> </nav> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> <div class=md-copyright__highlight> Copyright &copy; 2013-2026 Niels Lohmann </div> </div> <div class=md-social> <a href="https://github.com/nlohmann" target="_blank" rel="noopener" title="github.com" class="md-social__link"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 512 512"><!-- Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C436.2 457.8 504 362.9 504 252 504 113.3 391.5 8 252.8 8M105.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-Line truncated
+23 -23
View File
@@ -8,7 +8,7 @@ This macro sets how many nesting levels the operations that walk a value recurse
The operations are copying a value, comparing two values, serializing with [`dump`](https://json.nlohmann.me/api/basic_json/dump/index.md) or [`operator<<`](https://json.nlohmann.me/api/operator_ltlt/index.md), hashing with `std::hash`, [`merge_patch`](https://json.nlohmann.me/api/basic_json/merge_patch/index.md), [`update`](https://json.nlohmann.me/api/basic_json/update/index.md) with `merge_objects`, [`diff`](https://json.nlohmann.me/api/basic_json/diff/index.md), [`merge_diff`](https://json.nlohmann.me/api/basic_json/merge_diff/index.md), converting a value to another specialization of `basic_json`, destroying a value, and the binary writers [`to_cbor`](https://json.nlohmann.me/api/basic_json/to_cbor/index.md), [`to_msgpack`](https://json.nlohmann.me/api/basic_json/to_msgpack/index.md), [`to_ubjson`](https://json.nlohmann.me/api/basic_json/to_ubjson/index.md), [`to_bjdata`](https://json.nlohmann.me/api/basic_json/to_bjdata/index.md), and [`to_bon8`](https://json.nlohmann.me/api/basic_json/to_bon8/index.md). They share this one limit; none has a limit of its own. Recursing is the fastest way to walk a value, but a value nested deeply enough would exhaust the call stack, so the library recurses only as far as the limit and finishes the levels below with an explicit stack. This is what makes all of them safe for untrusted input (see [Nesting depth](https://json.nlohmann.me/features/parsing/untrusted_input/#nesting-depth)). Parsing, the binary readers, [`flatten`](https://json.nlohmann.me/api/basic_json/flatten/index.md), [`unflatten`](https://json.nlohmann.me/api/basic_json/unflatten/index.md), and [`to_bson`](https://json.nlohmann.me/api/basic_json/to_bson/index.md) always use an explicit stack and do not depend on the macro. The lockstep comparison of two [`json_view`](https://json.nlohmann.me/api/basic_json_view/index.md) documents has a fixed bound of its own, 48 levels, and does not depend on it either.
The call stack that these operations need grows with the limit: roughly *a few kilobytes plus a cost per level times the limit*, where the cost per level is up to about 2.3 KiB in an unoptimized and up to about 0.5 KiB in an optimized build (see [Stack needed](#stack-needed)). The default of `128` levels is tuned for threads with ordinary stacks of a few hundred kilobytes or more. Set a lower limit if your threads have small stacks (RTOS tasks, fibers, threads of the musl C library, which has a default stack of 128 KiB), or a higher limit to trade stack for speed on deeply nested values.
The call stack that these operations need grows with the limit: roughly *a few kilobytes plus a cost per level times the limit*, where the cost per level is up to about 1.8 KiB in an unoptimized and up to about 0.5 KiB in an optimized build (see [Stack needed](#stack-needed)). The default of `128` levels is tuned for threads with ordinary stacks of a few hundred kilobytes or more. Set a lower limit if your threads have small stacks (RTOS tasks, fibers, threads of the musl C library, which has a default stack of 128 KiB), or a higher limit to trade stack for speed on deeply nested values.
The macro changes only how much stack is used and how fast the operations are. It never changes a result: every operation returns the same value for every setting of the limit, for values nested less deeply than the limit as well as for values nested more deeply.
@@ -29,7 +29,7 @@ Allowed values
The value must be an integer constant expression from `0` to `254`; any other value (a negative number, a number above `254`, a floating-point number such as `254.0`, or `true` or `false`) is rejected at compile time with an error message that names the macro. A character of any character type (`'a'`, `L'a'`, `u8'a'`, ...) is rejected, too, although it is an integer.
- `0` is allowed, and means that every operation uses its explicit stack from the first level on and no operation recurses over the nesting of a value at all. That needs a constant amount of call stack (at most 16 KiB in the measurements below, for a value nested 20,000 levels deep) and is the setting for tiny stacks, at the price of speed (see [Speed](#speed)).
- `254` is the largest allowed value. Copying a value and comparing two values (with `<=>`, or with the operators on objects and arrays of a custom type) cannot pass the depth down as an argument, because the signatures of the copy constructor and the operators are fixed. They count the levels they have descended into in a variable of type `std::uint8_t` that exists once per thread (see [`JSON_NO_THREAD_LOCAL`](https://json.nlohmann.me/api/macros/json_no_thread_local/index.md)). Only the levels that are descended into are counted, so the count never exceeds the limit, not even when user code (a copy constructor of a custom base class, say) copies a value while a copy is going on. A byte holds `255` at most, and the limit stays below that, so that the count cannot wrap around. (More levels would hardly be useful: `254` levels need up to 576 KiB of stack in an unoptimized build already, twice as much as the default.)
- `254` is the largest allowed value. Copying a value and comparing two values (with `<=>`, or with the operators on objects and arrays of a custom type) cannot pass the depth down as an argument, because the signatures of the copy constructor and the operators are fixed. They count the levels they have descended into in a variable of type `std::uint8_t` that exists once per thread (see [`JSON_NO_THREAD_LOCAL`](https://json.nlohmann.me/api/macros/json_no_thread_local/index.md)). Only the levels that are descended into are counted, so the count never exceeds the limit, not even when user code (a copy constructor of a custom base class, say) copies a value while a copy is going on. A byte holds `255` at most, and the limit stays below that, so that the count cannot wrap around. (More levels would hardly be useful: `254` levels need up to 448 KiB of stack in an unoptimized build already, twice as much as the default.)
### Stack needed
@@ -37,21 +37,21 @@ The tables show the smallest stack that an operation needs, in KiB, at several l
Unoptimized (`-O0`):
| Operation | limit 16 | limit 32 | limit 64 | limit 128 | limit 254 |
| ----------------------------------------- | -------- | -------- | --------- | --------- | --------- |
| `dump()` and `dump(indent)`, `operator<<` | 48 / 32 | 80 / 64 | 144 / 128 | 288 / 256 | 576 / 512 |
| copy construction and assignment | 32 / 16 | 48 / 32 | 112 / 80 | 224 / 144 | 432 / 304 |
| `==` | 16 / 16 | 16 / 16 | 16 / 16 | 48 / 32 | 96 / 48 |
| `<=>` (C++20) | 16 / 16 | 16 / 16 | 32 / 32 | 64 / 64 | 144 / 128 |
| `std::hash` | 16 / 16 | 16 / 16 | 32 / 32 | 80 / 64 | 160 / 128 |
| `merge_patch`, `update(j, true)`, `patch` | 32 / 16 | 48 / 32 | 112 / 80 | 224 / 144 | 432 / 304 |
| `diff` | 16 / 16 | 16 / 16 | 32 / 32 | 64 / 48 | 144 / 96 |
| `merge_diff` | 16 / 16 | 48 / 32 | 80 / 48 | 176 / 112 | 352 / 224 |
| `to_cbor`, `to_msgpack` | 16 / 16 | 32 / 16 | 64 / 32 | 112 / 80 | 224 / 160 |
| `to_ubjson`, `to_bjdata` | 16 / 16 | 16 / 16 | 48 / 32 | 96 / 64 | 176 / 112 |
| `to_bon8` | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 16 | 64 / 48 |
| conversion to another `basic_json` type | 32 / 16 | 64 / 32 | 112 / 80 | 224 / 144 | 448 / 304 |
| destruction | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 32 |
| Operation | limit 16 | limit 32 | limit 64 | limit 128 | limit 254 |
| ----------------------------------------- | -------- | -------- | -------- | --------- | --------- |
| `dump()` and `dump(indent)`, `operator<<` | 16 / 16 | 16 / 16 | 32 / 32 | 48 / 48 | 96 / 96 |
| copy construction and assignment | 32 / 16 | 48 / 32 | 112 / 80 | 224 / 144 | 432 / 304 |
| `==` | 16 / 16 | 16 / 16 | 16 / 16 | 48 / 32 | 96 / 48 |
| `<=>` (C++20) | 16 / 16 | 16 / 16 | 32 / 32 | 64 / 64 | 144 / 128 |
| `std::hash` | 16 / 16 | 16 / 16 | 32 / 32 | 80 / 64 | 160 / 128 |
| `merge_patch`, `update(j, true)`, `patch` | 32 / 16 | 48 / 32 | 112 / 80 | 224 / 144 | 432 / 304 |
| `diff` | 16 / 16 | 16 / 16 | 32 / 32 | 64 / 48 | 144 / 96 |
| `merge_diff` | 16 / 16 | 48 / 32 | 80 / 48 | 176 / 112 | 352 / 224 |
| `to_cbor`, `to_msgpack` | 16 / 16 | 32 / 16 | 64 / 32 | 112 / 80 | 224 / 160 |
| `to_ubjson`, `to_bjdata` | 16 / 16 | 16 / 16 | 48 / 32 | 96 / 64 | 176 / 112 |
| `to_bon8` | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 16 | 64 / 48 |
| conversion to another `basic_json` type | 32 / 16 | 64 / 32 | 112 / 80 | 224 / 144 | 448 / 304 |
| destruction | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 32 |
Optimized (`-O2`):
@@ -77,17 +77,17 @@ The rule of thumb is
> stack needed ≈ a few KiB + cost per level × limit
with a cost per level of up to 2.3 KiB (`dump` at `-O0` with Clang; 2.1 KiB with GCC), 1.7 KiB for copying and merging (1.3 KiB with GCC), and 0.1 to 0.5 KiB for most other operations at `-O0`; and 0.5 KiB or less at `-O2`. The numbers come from the difference between the limits `128` and `254` in the tables, so they are rough: other compilers, other targets (the frames of x86-64 code are about as large), other standard libraries, `JSON_DIAGNOSTICS`, and sanitizers change them. Measure with your own tool chain (see the example below) rather than relying on the tables. The stack that your own code and the operating system need comes on top of these numbers.
with a cost per level of up to 1.8 KiB (conversion to another `basic_json` type at `-O0` with Clang; 1.3 KiB with GCC), 1.7 KiB for copying and merging (1.3 KiB with GCC), 0.4 KiB for `dump`, and 0.1 to 0.5 KiB for most other operations at `-O0`; and 0.5 KiB or less at `-O2`. The numbers come from the difference between the limits `128` and `254` in the tables, so they are rough: other compilers, other targets (the frames of x86-64 code are about as large), other standard libraries, `JSON_DIAGNOSTICS`, and sanitizers change them. Measure with your own tool chain (see the example below) rather than relying on the tables. The stack that your own code and the operating system need comes on top of these numbers.
Which limit to choose, for the stack that you can spare for the library (the largest limit of those measured for which the slowest operation needs at most that much):
| Stack for the library | optimized (`-O2`) | unoptimized (`-O0`) |
| ---------------------------------------------- | ----------------- | ------------------- |
| 32 KiB | 64 | 0 |
| 64 KiB | 128 | 16 |
| 128 KiB (the default stack of threads on musl) | 254 | 32 |
| 256 KiB | 254 | 64 |
| 512 KiB | 254 | 128 |
| 32 KiB | 64 | 16 |
| 64 KiB | 128 | 32 |
| 128 KiB (the default stack of threads on musl) | 254 | 64 |
| 256 KiB | 254 | 128 |
| 512 KiB | 254 | 254 |
| 1 MiB or more | 254 | 254 |
### Speed
+12 -10
View File
@@ -89,19 +89,21 @@ This differs from `#!cpp std::map`, where the same operations are O(log n).
!!! warning "Quadratic cost of building large objects"
Because every insertion scans all elements inserted so far, building an object of `n` distinct keys costs
**O(n²)** in total. This applies to filling an [`ordered_json`](ordered_json.md) object key by key as well as to
parsing one, since the parser inserts each key as it is read.
**O(n²)** in total. This applies to filling an [`ordered_json`](ordered_json.md) object key by key (with
`operator[]`, `emplace`, or `insert`) and, for now, to reading one with a binary reader such as
[`from_cbor`](basic_json/from_cbor.md) ([#6104](https://github.com/nlohmann/json/issues/6104)). Parsing JSON text
is not affected: the parser finds the keys of an object with many members in a hash table and takes linear time.
The cost is negligible for the object sizes typically found in configuration files or API payloads, but it grows
steeply for machine-generated objects with many thousands of keys. Measured with `-O2 -DNDEBUG` for parsing a flat
object of `n` keys, relative to `#!cpp nlohmann::json` (which uses `#!cpp std::map`):
steeply for machine-generated objects with many thousands of keys. Measured with Apple clang 21, `-O2 -DNDEBUG`,
arm64, for a flat object of `n` keys (best of seven runs):
| `n` | `json` | `ordered_json` | factor |
|--------|--------|----------------|--------|
| 2000 | 0.7 ms | 3.6 ms | 5× |
| 4000 | 0.8 ms | 14.0 ms | 19× |
| 8000 | 1.6 ms | 67.8 ms | 43× |
| 16 000 | 3.3 ms | 181.6 ms | 54× |
| `n` | `json::parse` | `ordered_json::parse` | `ordered_json`, key by key | `ordered_json::from_cbor` |
|--------|---------------|-----------------------|----------------------------|---------------------------|
| 2000 | 0.3 ms | 0.1 ms | 4.5 ms | 4.4 ms |
| 4000 | 0.5 ms | 0.2 ms | 17.1 ms | 16.8 ms |
| 8000 | 0.9 ms | 0.3 ms | 67.0 ms | 66.8 ms |
| 16 000 | 2.0 ms | 0.7 ms | 282.4 ms | 282.4 ms |
If key order matters for objects of that size, consider a container with a lookup index, such as
[`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map)
+2 -2
View File
@@ -4,7 +4,7 @@
</code></pre></div> <p>A minimal map-like container that preserves insertion order for use within <a href=../ordered_json/ ><code>nlohmann::ordered_json</code></a> (<code>nlohmann::basic_json&lt;ordered_map&gt;</code>).</p> <h2 id=template-parameters>Template parameters<a class=headerlink href=#template-parameters title="Permanent link">&para;</a></h2> <dl> <dt><code>Key</code></dt> <dd>key type</dd> <dt><code>T</code></dt> <dd>mapped type</dd> <dt><code>IgnoredLess</code></dt> <dd>comparison function (ignored and only added to ensure compatibility with <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>map</span></code>)</dd> <dt><code>Allocator</code></dt> <dd>allocator type</dd> </dl> <h2 id=iterator-invalidation>Iterator invalidation<a class=headerlink href=#iterator-invalidation title="Permanent link">&para;</a></h2> <p>The type uses a <code>std::vector</code> to store object elements. Therefore, adding elements can yield a reallocation in which case all iterators (including the <code>end()</code> iterator) and all references to the elements are invalidated.</p> <p>When the storage grows, the keys are copied and the mapped values are moved to the new storage. A plain <code>std::vector</code> would copy the whole elements instead, because their <code class=highlight><span class=k>const</span></code> keys make them not nothrow move constructible; for <a href=../ordered_json/ ><code>ordered_json</code></a>, this would be a deep copy of every nested value. The values are only copied if <code>T</code> is not default constructible or not nothrow move assignable.</p> <h2 id=member-types>Member types<a class=headerlink href=#member-types title="Permanent link">&para;</a></h2> <ul> <li><strong>key_type</strong> - key type (<code>Key</code>)</li> <li><strong>mapped_type</strong> - mapped type (<code>T</code>)</li> <li><strong>Container</strong> - base container type (<code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>vector</span><span class=o>&lt;</span><span class=n>std</span><span class=o>::</span><span class=n>pair</span><span class=o>&lt;</span><span class=k>const</span><span class=w> </span><span class=n>Key</span><span class=p>,</span><span class=w> </span><span class=n>T</span><span class=o>&gt;</span><span class=p>,</span><span class=w> </span><span class=n>Allocator</span><span class=o>&gt;</span></code>)</li> <li><strong>iterator</strong></li> <li><strong>const_iterator</strong></li> <li><strong>size_type</strong></li> <li><strong>value_type</strong></li> <li><strong>key_compare</strong> - key comparison function <div class=highlight><pre><span></span><code><span class=n>std</span><span class=o>::</span><span class=n>equal_to</span><span class=o>&lt;</span><span class=n>Key</span><span class=o>&gt;</span><span class=w> </span><span class=c1>// until C++14</span>
<span class=n>std</span><span class=o>::</span><span class=n>equal_to</span><span class=o>&lt;&gt;</span><span class=w> </span><span class=c1>// since C++14</span>
</code></pre></div></li> </ul> <h2 id=member-functions>Member functions<a class=headerlink href=#member-functions title="Permanent link">&para;</a></h2> <ul> <li>(constructor)</li> <li>(destructor)</li> <li><strong>emplace</strong></li> <li><strong>operator[]</strong></li> <li><strong>at</strong></li> <li><strong>erase</strong></li> <li><strong>count</strong></li> <li><strong>find</strong></li> <li><strong>insert</strong></li> </ul> <h2 id=exception-safety>Exception safety<a class=headerlink href=#exception-safety title="Permanent link">&para;</a></h2> <p><strong>emplace</strong>, <strong>operator[]</strong>, and <strong>insert(value)</strong> have the strong exception guarantee: if an exception is thrown (for instance, because copying a key or allocating memory fails), the contents of the container are unchanged.</p> <h2 id=complexity>Complexity<a class=headerlink href=#complexity title="Permanent link">&para;</a></h2> <p>Because the elements are stored in a <code>std::vector</code> in insertion order, there is no index to look a key up by. Every key-based operation performs a <strong>linear scan</strong> over the stored elements. With <code>n</code> denoting the number of elements in the container:</p> <table> <thead> <tr> <th>Operation</th> <th>Complexity</th> <th>Note</th> </tr> </thead> <tbody> <tr> <td><strong>emplace</strong></td> <td>O(n)</td> <td>scans for an existing key, then appends (amortized O(1))</td> </tr> <tr> <td><strong>operator[]</strong></td> <td>O(n)</td> <td>delegates to <strong>emplace</strong> (non-const) or <strong>at</strong> (const)</td> </tr> <tr> <td><strong>at</strong></td> <td>O(n)</td> <td>throws <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>out_of_range</span></code> if the key is not found</td> </tr> <tr> <td><strong>find</strong></td> <td>O(n)</td> <td></td> </tr> <tr> <td><strong>count</strong></td> <td>O(n)</td> <td>the result is always 0 or 1</td> </tr> <tr> <td><strong>erase(key)</strong></td> <td>O(n)</td> <td>scan, then move the remaining elements one position down</td> </tr> <tr> <td><strong>erase(pos)</strong>, <strong>erase(first, last)</strong></td> <td>O(n)</td> <td>moves all elements after the erased range</td> </tr> <tr> <td><strong>insert(value)</strong></td> <td>O(n)</td> <td>equivalent to <strong>emplace</strong></td> </tr> <tr> <td><strong>insert(first, last)</strong></td> <td>O((n + m) * m)</td> <td>for <code>m</code> inserted elements</td> </tr> </tbody> </table> <p>This differs from <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>map</span></code>, where the same operations are O(log n).</p> <div class="admonition warning"> <p class=admonition-title>Quadratic cost of building large objects</p> <p>Because every insertion scans all elements inserted so far, building an object of <code>n</code> distinct keys costs <strong>O(n²)</strong> in total. This applies to filling an <a href=../ordered_json/ ><code>ordered_json</code></a> object key by key as well as to parsing one, since the parser inserts each key as it is read.</p> <p>The cost is negligible for the object sizes typically found in configuration files or <abbr title="Application Programming Interface">API</abbr> payloads, but it grows steeply for machine-generated objects with many thousands of keys. Measured with <code>-O2 -DNDEBUG</code> for parsing a flat object of <code>n</code> keys, relative to <code class=highlight><span class=n>nlohmann</span><span class=o>::</span><span class=n>json</span></code> (which uses <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>map</span></code>):</p> <table> <thead> <tr> <th><code>n</code></th> <th><code>json</code></th> <th><code>ordered_json</code></th> <th>factor</th> </tr> </thead> <tbody> <tr> <td>2000</td> <td>0.7 ms</td> <td>3.6 ms</td> <td>5×</td> </tr> <tr> <td>4000</td> <td>0.8 ms</td> <td>14.0 ms</td> <td>19×</td> </tr> <tr> <td>8000</td> <td>1.6 ms</td> <td>67.8 ms</td> <td>43×</td> </tr> <tr> <td>16 000</td> <td>3.3 ms</td> <td>181.6 ms</td> <td>54×</td> </tr> </tbody> </table> <p>If key order matters for objects of that size, consider a container with a lookup index, such as <a href="https://github.com/nlohmann/fifo_map"><code>nlohmann::fifo_map</code></a> (<a href="https://github.com/nlohmann/json/issues/485#issuecomment-333652309">integration</a>), as the object type — see <a href=../../features/object_order/ >object order</a>.</p> </div> <h2 id=examples>Examples<a class=headerlink href=#examples title="Permanent link">&para;</a></h2> <details class=example> <summary>Example</summary> <p>The example shows the different behavior of <code>std::map</code> and <code>nlohmann::ordered_map</code>.</p> <div class=highlight><pre><span></span><code><span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;iostream&gt;</span>
</code></pre></div></li> </ul> <h2 id=member-functions>Member functions<a class=headerlink href=#member-functions title="Permanent link">&para;</a></h2> <ul> <li>(constructor)</li> <li>(destructor)</li> <li><strong>emplace</strong></li> <li><strong>operator[]</strong></li> <li><strong>at</strong></li> <li><strong>erase</strong></li> <li><strong>count</strong></li> <li><strong>find</strong></li> <li><strong>insert</strong></li> </ul> <h2 id=exception-safety>Exception safety<a class=headerlink href=#exception-safety title="Permanent link">&para;</a></h2> <p><strong>emplace</strong>, <strong>operator[]</strong>, and <strong>insert(value)</strong> have the strong exception guarantee: if an exception is thrown (for instance, because copying a key or allocating memory fails), the contents of the container are unchanged.</p> <h2 id=complexity>Complexity<a class=headerlink href=#complexity title="Permanent link">&para;</a></h2> <p>Because the elements are stored in a <code>std::vector</code> in insertion order, there is no index to look a key up by. Every key-based operation performs a <strong>linear scan</strong> over the stored elements. With <code>n</code> denoting the number of elements in the container:</p> <table> <thead> <tr> <th>Operation</th> <th>Complexity</th> <th>Note</th> </tr> </thead> <tbody> <tr> <td><strong>emplace</strong></td> <td>O(n)</td> <td>scans for an existing key, then appends (amortized O(1))</td> </tr> <tr> <td><strong>operator[]</strong></td> <td>O(n)</td> <td>delegates to <strong>emplace</strong> (non-const) or <strong>at</strong> (const)</td> </tr> <tr> <td><strong>at</strong></td> <td>O(n)</td> <td>throws <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>out_of_range</span></code> if the key is not found</td> </tr> <tr> <td><strong>find</strong></td> <td>O(n)</td> <td></td> </tr> <tr> <td><strong>count</strong></td> <td>O(n)</td> <td>the result is always 0 or 1</td> </tr> <tr> <td><strong>erase(key)</strong></td> <td>O(n)</td> <td>scan, then move the remaining elements one position down</td> </tr> <tr> <td><strong>erase(pos)</strong>, <strong>erase(first, last)</strong></td> <td>O(n)</td> <td>moves all elements after the erased range</td> </tr> <tr> <td><strong>insert(value)</strong></td> <td>O(n)</td> <td>equivalent to <strong>emplace</strong></td> </tr> <tr> <td><strong>insert(first, last)</strong></td> <td>O((n + m) * m)</td> <td>for <code>m</code> inserted elements</td> </tr> </tbody> </table> <p>This differs from <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>map</span></code>, where the same operations are O(log n).</p> <div class="admonition warning"> <p class=admonition-title>Quadratic cost of building large objects</p> <p>Because every insertion scans all elements inserted so far, building an object of <code>n</code> distinct keys costs <strong>O(n²)</strong> in total. This applies to filling an <a href=../ordered_json/ ><code>ordered_json</code></a> object key by key (with <code>operator[]</code>, <code>emplace</code>, or <code>insert</code>) and, for now, to reading one with a binary reader such as <a href=../basic_json/from_cbor/ ><code>from_cbor</code></a> (<a href="https://github.com/nlohmann/json/issues/6104">#6104</a>). Parsing <abbr title="JavaScript Object Notation">JSON</abbr> text is not affected: the parser finds the keys of an object with many members in a hash table and takes linear time.</p> <p>The cost is negligible for the object sizes typically found in configuration files or <abbr title="Application Programming Interface">API</abbr> payloads, but it grows steeply for machine-generated objects with many thousands of keys. Measured with Apple clang 21, <code>-O2 -DNDEBUG</code>, arm64, for a flat object of <code>n</code> keys (best of seven runs):</p> <table> <thead> <tr> <th><code>n</code></th> <th><code>json::parse</code></th> <th><code>ordered_json::parse</code></th> <th><code>ordered_json</code>, key by key</th> <th><code>ordered_json::from_cbor</code></th> </tr> </thead> <tbody> <tr> <td>2000</td> <td>0.3 ms</td> <td>0.1 ms</td> <td>4.5 ms</td> <td>4.4 ms</td> </tr> <tr> <td>4000</td> <td>0.5 ms</td> <td>0.2 ms</td> <td>17.1 ms</td> <td>16.8 ms</td> </tr> <tr> <td>8000</td> <td>0.9 ms</td> <td>0.3 ms</td> <td>67.0 ms</td> <td>66.8 ms</td> </tr> <tr> <td>16 000</td> <td>2.0 ms</td> <td>0.7 ms</td> <td>282.4 ms</td> <td>282.4 ms</td> </tr> </tbody> </table> <p>If key order matters for objects of that size, consider a container with a lookup index, such as <a href="https://github.com/nlohmann/fifo_map"><code>nlohmann::fifo_map</code></a> (<a href="https://github.com/nlohmann/json/issues/485#issuecomment-333652309">integration</a>), as the object type — see <a href=../../features/object_order/ >object order</a>.</p> </div> <h2 id=examples>Examples<a class=headerlink href=#examples title="Permanent link">&para;</a></h2> <details class=example> <summary>Example</summary> <p>The example sLine truncated
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;nlohmann/json.hpp&gt;</span>
<span class=c1>// simple output function</span>
@@ -51,4 +51,4 @@
<span class=err>m_s</span><span class=kc>t</span><span class=err>d</span><span class=w> </span><span class=err>=</span><span class=w> </span><span class=p>{</span><span class=w> </span><span class=err>o</span><span class=kc>ne</span><span class=p>:</span><span class=err>ei</span><span class=kc>ns</span><span class=w> </span><span class=kc>t</span><span class=err>hree</span><span class=p>:</span><span class=err>drei</span><span class=w> </span><span class=kc>t</span><span class=err>wo</span><span class=p>:</span><span class=err>zwei</span><span class=w> </span><span class=p>}</span>
<span class=err>m_ordered</span><span class=w> </span><span class=err>=</span><span class=w> </span><span class=p>{</span><span class=w> </span><span class=kc>t</span><span class=err>wo</span><span class=p>:</span><span class=err>zwei</span><span class=w> </span><span class=kc>t</span><span class=err>hree</span><span class=p>:</span><span class=err>drei</span><span class=w> </span><span class=err>o</span><span class=kc>ne</span><span class=p>:</span><span class=err>ei</span><span class=kc>ns</span><span class=w> </span><span class=p>}</span>
<span class=err>m_s</span><span class=kc>t</span><span class=err>d</span><span class=w> </span><span class=err>=</span><span class=w> </span><span class=p>{</span><span class=w> </span><span class=err>o</span><span class=kc>ne</span><span class=p>:</span><span class=err>ei</span><span class=kc>ns</span><span class=w> </span><span class=kc>t</span><span class=err>hree</span><span class=p>:</span><span class=err>drei</span><span class=w> </span><span class=kc>t</span><span class=err>wo</span><span class=p>:</span><span class=err>zwei</span><span class=w> </span><span class=p>}</span>
</code></pre></div> </details> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li><a href=../ordered_json/ ><code>ordered_json</code></a> - <abbr title="JavaScript Object Notation">JSON</abbr> specialization preserving insertion order</li> <li><a href=../../features/object_order/ >Object Order</a> - the article on object key order</li> </ul> <h2 id=version-history>Version history<a class=headerlink href=#version-history title="Permanent link">&para;</a></h2> <ul> <li>Added in version 3.9.0 to implement <a href=../ordered_json/ ><code>nlohmann::ordered_json</code></a>.</li> <li>Added <strong>key_compare</strong> member in version 3.11.0.</li> <li>Changed in version 3.13.0 <span class=unreleased-version title="Not part of a release yet; the latest release is 3.12.0.">unreleased</span>: growing the storage moves the mapped values instead of copying them.</li> </ul> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="October 27, 2026 06:41:42 UTC">October 27, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <nav class="md-footer__inner md-grid" aria-label=Footer> <a href=../ordered_json_view/ class="md-footer__link md-footer__link--prev" aria-label="Previous: ordered_json_view"> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg> </div> <div class=md-footer__title> <span class=md-footer__direction> Previous </span> <div class=md-ellipsis> ordered_json_view </div> </div> </a> <a href=../view_mode/ class="md-footer__link md-footer__link--next" aria-label="Next: view_mode"> <div class=md-footer__title> <span class=md-footer__direction> Next </span> <div class=md-ellipsis> view_mode </div> </div> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11z"/></svg> </div> </a> </nav> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> <div class=md-copyright__highlight> Copyright &copy; 2013-2026 Niels Lohmann </div> </div> <div class=md-social> <a href="https://github.com/nlohmann" target="_blank" rel="noopener" title="github.com" class="md-social__link"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 512 512"><!-- Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C436.2 457.8 504 362.9 504 252 504 113.3 391.5 8 252.8 8M105.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.Line truncated
</code></pre></div> </details> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li><a href=../ordered_json/ ><code>ordered_json</code></a> - <abbr title="JavaScript Object Notation">JSON</abbr> specialization preserving insertion order</li> <li><a href=../../features/object_order/ >Object Order</a> - the article on object key order</li> </ul> <h2 id=version-history>Version history<a class=headerlink href=#version-history title="Permanent link">&para;</a></h2> <ul> <li>Added in version 3.9.0 to implement <a href=../ordered_json/ ><code>nlohmann::ordered_json</code></a>.</li> <li>Added <strong>key_compare</strong> member in version 3.11.0.</li> <li>Changed in version 3.13.0 <span class=unreleased-version title="Not part of a release yet; the latest release is 3.12.0.">unreleased</span>: growing the storage moves the mapped values instead of copying them.</li> </ul> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="November 13, 2026 16:54:22 UTC">November 13, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <nav class="md-footer__inner md-grid" aria-label=Footer> <a href=../ordered_json_view/ class="md-footer__link md-footer__link--prev" aria-label="Previous: ordered_json_view"> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg> </div> <div class=md-footer__title> <span class=md-footer__direction> Previous </span> <div class=md-ellipsis> ordered_json_view </div> </div> </a> <a href=../view_mode/ class="md-footer__link md-footer__link--next" aria-label="Next: view_mode"> <div class=md-footer__title> <span class=md-footer__direction> Next </span> <div class=md-ellipsis> view_mode </div> </div> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11z"/></svg> </div> </a> </nav> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> <div class=md-copyright__highlight> Copyright &copy; 2013-2026 Niels Lohmann </div> </div> <div class=md-social> <a href="https://github.com/nlohmann" target="_blank" rel="noopener" title="github.com" class="md-social__link"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 512 512"><!-- Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C436.2 457.8 504 362.9 504 252 504 113.3 391.5 8 252.8 8M105.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 Line truncated
+8 -8
View File
@@ -84,16 +84,16 @@ This differs from `std::map`, where the same operations are O(log n).
Quadratic cost of building large objects
Because every insertion scans all elements inserted so far, building an object of `n` distinct keys costs **O(n²)** in total. This applies to filling an [`ordered_json`](https://json.nlohmann.me/api/ordered_json/index.md) object key by key as well as to parsing one, since the parser inserts each key as it is read.
Because every insertion scans all elements inserted so far, building an object of `n` distinct keys costs **O(n²)** in total. This applies to filling an [`ordered_json`](https://json.nlohmann.me/api/ordered_json/index.md) object key by key (with `operator[]`, `emplace`, or `insert`) and, for now, to reading one with a binary reader such as [`from_cbor`](https://json.nlohmann.me/api/basic_json/from_cbor/index.md) ([#6104](https://github.com/nlohmann/json/issues/6104)). Parsing JSON text is not affected: the parser finds the keys of an object with many members in a hash table and takes linear time.
The cost is negligible for the object sizes typically found in configuration files or API payloads, but it grows steeply for machine-generated objects with many thousands of keys. Measured with `-O2 -DNDEBUG` for parsing a flat object of `n` keys, relative to `nlohmann::json` (which uses `std::map`):
The cost is negligible for the object sizes typically found in configuration files or API payloads, but it grows steeply for machine-generated objects with many thousands of keys. Measured with Apple clang 21, `-O2 -DNDEBUG`, arm64, for a flat object of `n` keys (best of seven runs):
| `n` | `json` | `ordered_json` | factor |
| ------ | ------ | -------------- | ------ |
| 2000 | 0.7 ms | 3.6 ms | 5× |
| 4000 | 0.8 ms | 14.0 ms | 19× |
| 8000 | 1.6 ms | 67.8 ms | 43× |
| 16 000 | 3.3 ms | 181.6 ms | 54× |
| `n` | `json::parse` | `ordered_json::parse` | `ordered_json`, key by key | `ordered_json::from_cbor` |
| ------ | ------------- | --------------------- | -------------------------- | ------------------------- |
| 2000 | 0.3 ms | 0.1 ms | 4.5 ms | 4.4 ms |
| 4000 | 0.5 ms | 0.2 ms | 17.1 ms | 16.8 ms |
| 8000 | 0.9 ms | 0.3 ms | 67.0 ms | 66.8 ms |
| 16 000 | 2.0 ms | 0.7 ms | 282.4 ms | 282.4 ms |
If key order matters for objects of that size, consider a container with a lookup index, such as [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map) ([integration](https://github.com/nlohmann/json/issues/485#issuecomment-333652309)), as the object type — see [object order](https://json.nlohmann.me/features/object_order/index.md).
+4 -1
View File
@@ -204,7 +204,10 @@ of the message are reported as [parse_error.110](../../home/exceptions.md#jsonex
arrays and objects with up to four elements that are terminated by 0xFE, unsorted object keys, or a 0xFF after a
string that would also end without it, are accepted. A second 0xFF is not a terminator but an empty string.
Strings must be valid UTF-8, and a string at the very end of a message must be terminated by 0xFF.
Strings must be valid UTF-8, and a string at the very end of a message must be terminated by 0xFF. This also
holds when `strict` is false and more data follows the value: the byte that would end the string belongs to the
next value, and reading it would remove it from the input, so the missing 0xFF is reported as
[parse_error.110](../../home/exceptions.md#jsonexceptionparse_error110).
Duplicate object keys are accepted; the last value wins (`ordered_json` keeps the position of the first occurrence).
The specification does not say how to treat them; the HikoGUI reference decoder keeps the first value.
+2 -2
View File
@@ -30,7 +30,7 @@
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o>&lt;&lt;</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
<span class=p>}</span>
</code></pre></div> <p>Output:</p> <div class=highlight><pre><span></span><code><span class=mh>0x89</span><span class=w> </span><span class=mh>0x63</span><span class=w> </span><span class=mh>0x6f</span><span class=w> </span><span class=mh>0x6d</span><span class=w> </span><span class=mh>0x70</span><span class=w> </span><span class=mh>0x61</span><span class=w> </span><span class=mh>0x63</span><span class=w> </span><span class=mh>0x74</span><span class=w> </span><span class=mh>0xf9</span><span class=w> </span><span class=mh>0x66</span><span class=w> </span><span class=mh>0x6f</span><span class=w> </span><span class=mh>0x72</span><span class=w> </span><span class=mh>0x6d</span><span class=w> </span><span class=mh>0x61</span><span class=w> </span><span class=mh>0x74</span><span class=w> </span><span class=mh>0xff</span><span class=w> </span><span class=mh>0x42</span><span class=w> </span><span class=mh>0x4f</span><span class=w> </span><span class=mh>0x4e</span><span class=w> </span><span class=mh>0x38</span><span class=w> </span><span class=mh>0xff</span><span class=w> </span><span class=mh>0x73</span><span class=w> </span><span class=mh>0x63</span><span class=w> </span><span class=mh>0x68</span><span class=w> </span><span class=mh>0x65</span><span class=w> </span><span class=mh>0x6d</span><span class=w> </span><span class=mh>0x61</span><span class=w> </span><span class=mh>0x90</span><span class=w> </span>
</code></pre></div> </details> <h2 id=deserialization>Deserialization<a class=headerlink href=#deserialization title="Permanent link">&para;</a></h2> <p>The library maps <abbr title="Binary Object Notation 8">BON8</abbr> types to <abbr title="JavaScript Object Notation">JSON</abbr> value types as follows:</p> <table> <thead> <tr> <th><abbr title="Binary Object Notation 8">BON8</abbr> type</th> <th><abbr title="JavaScript Object Notation">JSON</abbr> value type</th> <th>first byte</th> </tr> </thead> <tbody> <tr> <td><abbr title="Unicode Transformation Format">UTF</abbr>-8 string</td> <td>string</td> <td>0x00..0x7F</td> </tr> <tr> <td>array with count</td> <td>array</td> <td>0x80..0x84</td> </tr> <tr> <td>array (terminated by 0xFE)</td> <td>array</td> <td>0x85</td> </tr> <tr> <td>object with count</td> <td>object</td> <td>0x86..0x8A</td> </tr> <tr> <td>object (terminated by 0xFE)</td> <td>object</td> <td>0x8B</td> </tr> <tr> <td>int32</td> <td>number_unsigned or number_integer</td> <td>0x8C</td> </tr> <tr> <td>int64</td> <td>number_unsigned or number_integer</td> <td>0x8D</td> </tr> <tr> <td>binary32</td> <td>number_float</td> <td>0x8E</td> </tr> <tr> <td>binary64</td> <td>number_float</td> <td>0x8F</td> </tr> <tr> <td>1-byte positive integer</td> <td>number_unsigned</td> <td>0x90..0xB7</td> </tr> <tr> <td>1-byte negative integer</td> <td>number_integer</td> <td>0xB8..0xC1</td> </tr> <tr> <td><abbr title="Unicode Transformation Format">UTF</abbr>-8 string</td> <td>string</td> <td>0xC2..0xF4, followed by 0x80..0xBF</td> </tr> <tr> <td>2- to 4-byte positive integer</td> <td>number_unsigned</td> <td>0xC2..0xF7, followed by 0x00..0x7F</td> </tr> <tr> <td>2- to 4-byte negative integer</td> <td>number_integer</td> <td>0xC2..0xF7, followed by 0xC0..0xFF</td> </tr> <tr> <td>false</td> <td><code>false</code></td> <td>0xF8</td> </tr> <tr> <td>true</td> <td><code>true</code></td> <td>0xF9</td> </tr> <tr> <td>null</td> <td><code>null</code></td> <td>0xFA</td> </tr> <tr> <td>-1.0</td> <td>number_float</td> <td>0xFB</td> </tr> <tr> <td>0.0</td> <td>number_float</td> <td>0xFC</td> </tr> <tr> <td>1.0</td> <td>number_float</td> <td>0xFD</td> </tr> <tr> <td>empty string</td> <td>string</td> <td>0xFF</td> </tr> </tbody> </table> <p>Non-negative integers are read as number_unsigned, negative integers as number_integer.</p> <p>A byte 0xF5..0xF7 followed by 0x80..0xBF is neither a string nor an integer and is rejected with <a href=../../../home/exceptions/#jsonexceptionparse_error112>parse_error.112</a> (invalid <abbr title="Unicode Transformation Format">UTF</abbr>-8 byte). The same error is reported for any other invalid byte (such as a stray 0xFE), for ill-formed <abbr title="Unicode Transformation Format">UTF</abbr>-8, and for an object key that is not a string. Input that ends prematurely, trailing data after the value, and a missing final 0xFF after a string at the end of the message are reported as <a href=../../../home/exceptions/#jsonexceptionparse_error110>parse_error.110</a>.</p> <div class="admonition info"> <p class=admonition-title>Non-canonical input</p> <p>Values that do not use the canonical representation, such as integers with a longer encoding than necessary, arrays and objects with up to four elements that are terminated by 0xFE, unsorted object keys, or a 0xFF after a string that would also end without it, are accepted. A second 0xFF is not a terminator but an empty string.</p> <p>Strings must be valid <abbr title="Unicode Transformation Format">UTF</abbr>-8, and a string at the very end of a message must be terminated by 0xFF.</p> <p>Duplicate object keys are accepted; the last value wins (<code>ordered_json</code> keeps the position of the first occurrence). The specification does not say how to treat them; the HikoGUI reference decoder keeps the first value.</p> </div> <div class="admonition info"> <p class=admonition-title>Round trips</p> <p>Any <abbr title="Binary Object Notation 8">BON8</abbr> output created by <code>to_bon8</code> can be successfully parsed by <code>from_bon8</code>.</p> </div> <details class=example> <summary>Example: deserialize a <abbr title="JavaScript Object Notation">JSON</abbr> value from <abbr title="Binary Object Notation 8">BON8</abbr></summary> <div class=highlight><pre><span></span><code><span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;iostream&gt;</span>
</code></pre></div> </details> <h2 id=deserialization>Deserialization<a class=headerlink href=#deserialization title="Permanent link">&para;</a></h2> <p>The library maps <abbr title="Binary Object Notation 8">BON8</abbr> types to <abbr title="JavaScript Object Notation">JSON</abbr> value types as follows:</p> <table> <thead> <tr> <th><abbr title="Binary Object Notation 8">BON8</abbr> type</th> <th><abbr title="JavaScript Object Notation">JSON</abbr> value type</th> <th>first byte</th> </tr> </thead> <tbody> <tr> <td><abbr title="Unicode Transformation Format">UTF</abbr>-8 string</td> <td>string</td> <td>0x00..0x7F</td> </tr> <tr> <td>array with count</td> <td>array</td> <td>0x80..0x84</td> </tr> <tr> <td>array (terminated by 0xFE)</td> <td>array</td> <td>0x85</td> </tr> <tr> <td>object with count</td> <td>object</td> <td>0x86..0x8A</td> </tr> <tr> <td>object (terminated by 0xFE)</td> <td>object</td> <td>0x8B</td> </tr> <tr> <td>int32</td> <td>number_unsigned or number_integer</td> <td>0x8C</td> </tr> <tr> <td>int64</td> <td>number_unsigned or number_integer</td> <td>0x8D</td> </tr> <tr> <td>binary32</td> <td>number_float</td> <td>0x8E</td> </tr> <tr> <td>binary64</td> <td>number_float</td> <td>0x8F</td> </tr> <tr> <td>1-byte positive integer</td> <td>number_unsigned</td> <td>0x90..0xB7</td> </tr> <tr> <td>1-byte negative integer</td> <td>number_integer</td> <td>0xB8..0xC1</td> </tr> <tr> <td><abbr title="Unicode Transformation Format">UTF</abbr>-8 string</td> <td>string</td> <td>0xC2..0xF4, followed by 0x80..0xBF</td> </tr> <tr> <td>2- to 4-byte positive integer</td> <td>number_unsigned</td> <td>0xC2..0xF7, followed by 0x00..0x7F</td> </tr> <tr> <td>2- to 4-byte negative integer</td> <td>number_integer</td> <td>0xC2..0xF7, followed by 0xC0..0xFF</td> </tr> <tr> <td>false</td> <td><code>false</code></td> <td>0xF8</td> </tr> <tr> <td>true</td> <td><code>true</code></td> <td>0xF9</td> </tr> <tr> <td>null</td> <td><code>null</code></td> <td>0xFA</td> </tr> <tr> <td>-1.0</td> <td>number_float</td> <td>0xFB</td> </tr> <tr> <td>0.0</td> <td>number_float</td> <td>0xFC</td> </tr> <tr> <td>1.0</td> <td>number_float</td> <td>0xFD</td> </tr> <tr> <td>empty string</td> <td>string</td> <td>0xFF</td> </tr> </tbody> </table> <p>Non-negative integers are read as number_unsigned, negative integers as number_integer.</p> <p>A byte 0xF5..0xF7 followed by 0x80..0xBF is neither a string nor an integer and is rejected with <a href=../../../home/exceptions/#jsonexceptionparse_error112>parse_error.112</a> (invalid <abbr title="Unicode Transformation Format">UTF</abbr>-8 byte). The same error is reported for any other invalid byte (such as a stray 0xFE), for ill-formed <abbr title="Unicode Transformation Format">UTF</abbr>-8, and for an object key that is not a string. Input that ends prematurely, trailing data after the value, and a missing final 0xFF after a string at the end of the message are reported as <a href=../../../home/exceptions/#jsonexceptionparse_error110>parse_error.110</a>.</p> <div class="admonition info"> <p class=admonition-title>Non-canonical input</p> <p>Values that do not use the canonical representation, such as integers with a longer encoding than necessary, arrays and objects with up to four elements that are terminated by 0xFE, unsorted object keys, or a 0xFF after a string that would also end without it, are accepted. A second 0xFF is not a terminator but an empty string.</p> <p>Strings must be valid <abbr title="Unicode Transformation Format">UTF</abbr>-8, and a string at the very end of a message must be terminated by 0xFF. This also holds when <code>strict</code> is false and more data follows the value: the byte that would end the string belongs to the next value, and reading it would remove it from the input, so the missing 0xFF is reported as <a href=../../../home/exceptions/#jsonexceptionparse_error110>parse_error.110</a>.</p> <p>Duplicate object keys are accepted; the last value wins (<code>ordered_json</code> keeps the position of the first occurrence). The specification does not say how to treat them; the HikoGUI reference decoder keeps the first value.</p> </div> <div class="admonition info"> <p class=admonition-title>Round trips</p> <p>Any <abbr title="Binary Object Notation 8">BON8</abbr> output created by <code>to_bon8</code> can be successfully parsed by <code>from_bon8</code>.</p> </div> <details class=example> <summary>Example: deserialize a <abbr title="JavaScript Object Notation">JSON</abbr> value from <abbr title="Binary Object Notation 8">BON8</abbr></summary> <div class=highlight><pre><span></span><code><span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;iostream&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;iomanip&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;nlohmann/json.hpp&gt;</span>
@@ -56,4 +56,4 @@
<span class=w> </span><span class=nt>"format"</span><span class=p>:</span><span class=w> </span><span class=s2>"BON8"</span><span class=p>,</span>
<span class=w> </span><span class=nt>"schema"</span><span class=p>:</span><span class=w> </span><span class=mi>0</span>
<span class=p>}</span>
</code></pre></div> </details> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li><a href=../ >Binary formats</a> - overview and comparison of the supported binary formats</li> <li><a href=../../binary_values/ >Binary values</a> - how binary values and subtypes map to <abbr title="Binary Object Notation 8">BON8</abbr></li> <li><a href=../../../api/basic_json/to_bon8/ ><code>to_bon8</code></a> - serialize a <abbr title="JavaScript Object Notation">JSON</abbr> value to <abbr title="Binary Object Notation 8">BON8</abbr></li> <li><a href=../../../api/basic_json/from_bon8/ ><code>from_bon8</code></a> - parse a <abbr title="JavaScript Object Notation">JSON</abbr> value from <abbr title="Binary Object Notation 8">BON8</abbr></li> <li><a href=../../../api/macros/json_strict_binary_utf8/ ><code>JSON_STRICT_BINARY_UTF8</code></a> - reject ill-formed <abbr title="Unicode Transformation Format">UTF</abbr>-8 in strings</li> <li><a href=../../parsing/sax_interface/ ><abbr title="Simple API for XML">SAX</abbr> interface</a> - decode binary formats without building a value</li> </ul> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="October 27, 2026 06:41:42 UTC">October 27, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <nav class="md-footer__inner md-grid" aria-label=Footer> <a href=../bjdata/ class="md-footer__link md-footer__link--prev" aria-label="Previous: BJData"> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg> </div> <div class=md-footer__title> <span class=md-footer__direction> Previous </span> <div class=md-ellipsis> BJData </div> </div> </a> <a href=../bson/ class="md-footer__link md-footer__link--next" aria-label="Next: BSON"> <div class=md-footer__title> <span class=md-footer__direction> Next </span> <div class=md-ellipsis> BSON </div> </div> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11z"/></svg> </div> </a> </nav> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> <div class=md-copyright__highlight> Copyright &copy; 2013-2026 Niels Lohmann </div> </div> <div class=md-social> <a href="https://github.com/nlohmann" target="_blank" rel="noopener" title="github.com" class="md-social__link"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 512 512"><!-- Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46Line truncated
</code></pre></div> </details> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li><a href=../ >Binary formats</a> - overview and comparison of the supported binary formats</li> <li><a href=../../binary_values/ >Binary values</a> - how binary values and subtypes map to <abbr title="Binary Object Notation 8">BON8</abbr></li> <li><a href=../../../api/basic_json/to_bon8/ ><code>to_bon8</code></a> - serialize a <abbr title="JavaScript Object Notation">JSON</abbr> value to <abbr title="Binary Object Notation 8">BON8</abbr></li> <li><a href=../../../api/basic_json/from_bon8/ ><code>from_bon8</code></a> - parse a <abbr title="JavaScript Object Notation">JSON</abbr> value from <abbr title="Binary Object Notation 8">BON8</abbr></li> <li><a href=../../../api/macros/json_strict_binary_utf8/ ><code>JSON_STRICT_BINARY_UTF8</code></a> - reject ill-formed <abbr title="Unicode Transformation Format">UTF</abbr>-8 in strings</li> <li><a href=../../parsing/sax_interface/ ><abbr title="Simple API for XML">SAX</abbr> interface</a> - decode binary formats without building a value</li> </ul> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="November 13, 2026 16:54:30 UTC">November 13, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <nav class="md-footer__inner md-grid" aria-label=Footer> <a href=../bjdata/ class="md-footer__link md-footer__link--prev" aria-label="Previous: BJData"> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg> </div> <div class=md-footer__title> <span class=md-footer__direction> Previous </span> <div class=md-ellipsis> BJData </div> </div> </a> <a href=../bson/ class="md-footer__link md-footer__link--next" aria-label="Next: BSON"> <div class=md-footer__title> <span class=md-footer__direction> Next </span> <div class=md-ellipsis> BSON </div> </div> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11z"/></svg> </div> </a> </nav> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> <div class=md-copyright__highlight> Copyright &copy; 2013-2026 Niels Lohmann </div> </div> <div class=md-social> <a href="https://github.com/nlohmann" target="_blank" rel="noopener" title="github.com" class="md-social__link"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 512 512"><!-- Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 Line truncated
+1 -1
View File
@@ -179,7 +179,7 @@ Non-canonical input
Values that do not use the canonical representation, such as integers with a longer encoding than necessary, arrays and objects with up to four elements that are terminated by 0xFE, unsorted object keys, or a 0xFF after a string that would also end without it, are accepted. A second 0xFF is not a terminator but an empty string.
Strings must be valid UTF-8, and a string at the very end of a message must be terminated by 0xFF.
Strings must be valid UTF-8, and a string at the very end of a message must be terminated by 0xFF. This also holds when `strict` is false and more data follows the value: the byte that would end the string belongs to the next value, and reading it would remove it from the input, so the missing 0xFF is reported as [parse_error.110](https://json.nlohmann.me/home/exceptions/#jsonexceptionparse_error110).
Duplicate object keys are accepted; the last value wins (`ordered_json` keeps the position of the first occurrence). The specification does not say how to treat them; the HikoGUI reference decoder keeps the first value.
+36 -6
View File
@@ -64,13 +64,13 @@ stack for the nesting.)
The call stack still needs room for the levels that are recursed into, and the default limit assumes a stack of ordinary
size. The stack that an operation needs is roughly proportional to the limit; with the default of 128 levels, the most
demanding operation (`dump` in an unoptimized build) needed up to 288 KiB, and an optimized build needed 48 KiB or less,
in measurements on macOS with arm64. The most demanding operation needed this much stack at the limits `0`, `32`,
`128`, and `254`:
demanding operations (copying a value and converting it to another `basic_json` type, in an unoptimized build) needed
up to 224 KiB, and an optimized build needed 48 KiB or less, in measurements on macOS with arm64. The most demanding
operation needed this much stack at the limits `0`, `32`, `128`, and `254`:
| Stack needed, in KiB | limit 0 | limit 32 | limit 128 (default) | limit 254 |
|---|---:|---:|---:|---:|
| unoptimized build (`-O0`) | 16 or less | 80 | 288 | 576 |
| unoptimized build (`-O0`) | 16 or less | 64 | 224 | 448 |
| optimized build (`-O2`) | 16 or less | 16 or less | 48 | 112 |
A thread with a smaller stack (a task of a real-time operating system, a fiber, or a thread of the musl C library, whose
@@ -81,6 +81,20 @@ result. See the [documentation of the macro](../../api/macros/json_recursion_dep
the speed, and the rules for choosing a value. Destroying a value (its destructor) recurses over the same number of
levels and then continues without the call stack, and needs 32 KiB or less at every limit.
!!! warning "Indented output and flattened keys grow with the depth"
Some results are larger than the value by a factor of its nesting depth.
[`dump`](../../api/basic_json/dump.md) with an `indent` of `n` (and likewise `operator<<` with `std::setw(n)` and
[`basic_json_view::dump`](../../api/basic_json_view/dump.md)) writes up to `n` characters per nesting level in
front of every line, and [`flatten`](../../api/basic_json/flatten.md) repeats the path of every value in its key.
For the 80,001-byte array `[1,[1,...[1,1]...]]` with 20,000 levels, `dump(1)` returns 600 MB, `dump(4)` 2.4 GB,
and the keys of `flatten()` hold 400 MB. A compact `dump()` without indentation stays the size of the value. If you
pretty-print, log, or flatten untrusted input, limit its nesting depth while parsing, for example with a
[parser callback](parser_callbacks.md#recipe-max-nesting-depth-via-a-callback): with a limit of `d`, every line has
at most `n * d` indentation characters, and every flattened key has at most `d` reference tokens.
[`JSON_RECURSION_DEPTH_LIMIT`](../../api/macros/json_recursion_depth_limit.md) does not help here: it changes only
how much of the call stack a walk uses, never its result, and it does not limit the depth that `parse()` accepts.
## Input size
The library does not limit the overall size of a JSON text; a value nested or wide enough will use memory
@@ -140,6 +154,20 @@ values for a repeated key ends up in the parsed object. If your application must
silently resolving them one way or another, see the
[parser callback recipe for rejecting duplicate keys](parser_callbacks.md#recipe-rejecting-duplicate-object-keys).
## Objects with many keys in `ordered_json`
[`ordered_json`](../../api/ordered_json.md) keeps the members of an object in a vector in insertion order
([`ordered_map`](../../api/ordered_map.md)) and finds a key by searching all members. Parsing JSON text into an
`ordered_json` avoids that search for objects with many keys and takes linear time. The binary readers
([`from_cbor`](../../api/basic_json/from_cbor.md), [`from_msgpack`](../../api/basic_json/from_msgpack.md),
[`from_ubjson`](../../api/basic_json/from_ubjson.md), [`from_bjdata`](../../api/basic_json/from_bjdata.md),
[`from_bson`](../../api/basic_json/from_bson.md), and [`from_bon8`](../../api/basic_json/from_bon8.md)) do not yet:
reading an object of `n` keys into an `ordered_json` costs time proportional to `n²`. A flat object of 40,000 keys
(about 300 KB of CBOR) takes about 1.3 s, against a few milliseconds as JSON text or into a `json`
([#6104](https://github.com/nlohmann/json/issues/6104)). `json` is not affected. If you read untrusted binary input
into `ordered_json`, bound the input size more tightly, read it into a `json`, or reject objects with many keys in a
[SAX handler](sax_interface.md).
## Numbers
A number whose value cannot be represented — for instance `1E1000`, which overflows `double` — is rejected while
@@ -171,9 +199,11 @@ indices (or the pointer as a whole) before using them, or use [`at`](../../api/b
- Wrap parsing in a `#!cpp try`/`#!cpp catch` block, or use `allow_exceptions=false`/`accept()` if your environment
cannot use exceptions; never let `JSON_NOEXCEPTION`'s `abort()` be the first time you think about error handling.
- If the input's nesting depth matters to you, enforce your own limit with a
[parser callback](parser_callbacks.md#recipe-max-nesting-depth-via-a-callback) or a
- If the input's nesting depth matters to you (for example because you pretty-print, log, or flatten it), enforce your
own limit with a [parser callback](parser_callbacks.md#recipe-max-nesting-depth-via-a-callback) or a
[SAX handler](sax_interface.md); the library bounds the call stack but not memory use.
- If you read untrusted binary input into `ordered_json`, mind that objects with many keys are
[slow to read](#objects-with-many-keys-in-ordered_json).
- Bound the size of the input itself before parsing, independent of the library's own bounded allocations for binary
format lengths.
- Decide up front how you want a string with invalid UTF-8 — from any source, not only parsing — to be serialized
+1 -1
View File
@@ -1 +1 @@
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content="JSON for Modern C++ is a header-only C++11 library that makes JSON a first-class data type."><meta name=author content="Niels Lohmann"><link href="https://json.nlohmann.me/features/parsing/untrusted_input/" rel="canonical"><link href=../sax_interface/ rel=prev><link href=../../assertions/ rel=next><link rel=icon href=../../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.8.0"><title>Parsing Untrusted Input - JSON for Modern C++</title><link rel=stylesheet href=../../../assets/stylesheets/main.57a0d79d.min.css><link rel=stylesheet href=../../../assets/stylesheets/palette.fb2fffe2.min.css><link rel=stylesheet href=../../../css/custom.css><link rel=stylesheet href=../../../css/brand.css><link rel=stylesheet href=../../../css/fig-sax.css><link rel=stylesheet href=../../../css/fig-jsonview.css><link rel=stylesheet href=../../../css/fig-exceptions.css><link rel=stylesheet href=../../../css/fig-pointer.css><link rel=stylesheet href=../../../css/fig-charts.css><link rel=stylesheet href=../../../css/fig-integration.css><link rel=stylesheet href=../../../css/fig-macros.css><script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script></head> <body dir=ltr data-md-color-scheme=default data-md-color-primary=custom data-md-color-accent=custom> <input class=md-toggle data-md-toggle=drawer type=checkbox id=__drawer autocomplete=off> <input class=md-toggle data-md-toggle=search type=checkbox id=__search autocomplete=off> <label class=md-overlay for=__drawer></label> <div data-md-component=skip> <a href=#parsing-untrusted-input class=md-skip> Skip to content </a> </div> <div data-md-component=announce> </div> <header class=md-header data-md-component=header> <nav class="md-header__inner md-grid" aria-label=Header> <a href=../../.. title="JSON for Modern C++" class="md-header__button md-logo" aria-label="JSON for Modern C++" data-md-component=logo> <img src=../../../images/wordmark-header.svg alt=logo> </a> <label class="md-header__button md-icon" for=__drawer> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg> </label> <div class=md-header__title data-md-component=header-title> <div class=md-header__ellipsis> <div class=md-header__topic> <span class=md-ellipsis> JSON for Modern C++ </span> </div> <div class=md-header__topic data-md-component=header-topic> <span class=md-ellipsis> Parsing Untrusted Input </span> </div> </div> </div> <form class=md-header__option data-md-component=palette> <input class=md-option data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme=default data-md-color-primary=custom data-md-color-accent=custom aria-label="Switch to dark mode" type=radio name=__palette id=__palette_0> <label class="md-header__button md-icon" title="Switch to dark mode" for=__palette_1 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> <input class=md-option data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme=slate data-md-color-primary=custom data-md-color-accent=custom aria-label="Switch to light mode" type=radio name=__palette id=__palette_1> <label class="md-header__button md-icon" title="Switch to light mode" for=__palette_0 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> </form> <script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script> <label class="md-header__button md-icon" for=__search> <svg xmlns=http://www.w3.org/2000/svgLine truncated
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content="JSON for Modern C++ is a header-only C++11 library that makes JSON a first-class data type."><meta name=author content="Niels Lohmann"><link href="https://json.nlohmann.me/features/parsing/untrusted_input/" rel="canonical"><link href=../sax_interface/ rel=prev><link href=../../assertions/ rel=next><link rel=icon href=../../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.8.0"><title>Parsing Untrusted Input - JSON for Modern C++</title><link rel=stylesheet href=../../../assets/stylesheets/main.57a0d79d.min.css><link rel=stylesheet href=../../../assets/stylesheets/palette.fb2fffe2.min.css><link rel=stylesheet href=../../../css/custom.css><link rel=stylesheet href=../../../css/brand.css><link rel=stylesheet href=../../../css/fig-sax.css><link rel=stylesheet href=../../../css/fig-jsonview.css><link rel=stylesheet href=../../../css/fig-exceptions.css><link rel=stylesheet href=../../../css/fig-pointer.css><link rel=stylesheet href=../../../css/fig-charts.css><link rel=stylesheet href=../../../css/fig-integration.css><link rel=stylesheet href=../../../css/fig-macros.css><script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script></head> <body dir=ltr data-md-color-scheme=default data-md-color-primary=custom data-md-color-accent=custom> <input class=md-toggle data-md-toggle=drawer type=checkbox id=__drawer autocomplete=off> <input class=md-toggle data-md-toggle=search type=checkbox id=__search autocomplete=off> <label class=md-overlay for=__drawer></label> <div data-md-component=skip> <a href=#parsing-untrusted-input class=md-skip> Skip to content </a> </div> <div data-md-component=announce> </div> <header class=md-header data-md-component=header> <nav class="md-header__inner md-grid" aria-label=Header> <a href=../../.. title="JSON for Modern C++" class="md-header__button md-logo" aria-label="JSON for Modern C++" data-md-component=logo> <img src=../../../images/wordmark-header.svg alt=logo> </a> <label class="md-header__button md-icon" for=__drawer> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg> </label> <div class=md-header__title data-md-component=header-title> <div class=md-header__ellipsis> <div class=md-header__topic> <span class=md-ellipsis> JSON for Modern C++ </span> </div> <div class=md-header__topic data-md-component=header-topic> <span class=md-ellipsis> Parsing Untrusted Input </span> </div> </div> </div> <form class=md-header__option data-md-component=palette> <input class=md-option data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme=default data-md-color-primary=custom data-md-color-accent=custom aria-label="Switch to dark mode" type=radio name=__palette id=__palette_0> <label class="md-header__button md-icon" title="Switch to dark mode" for=__palette_1 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> <input class=md-option data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme=slate data-md-color-primary=custom data-md-color-accent=custom aria-label="Switch to light mode" type=radio name=__palette id=__palette_1> <label class="md-header__button md-icon" title="Switch to light mode" for=__palette_0 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> </form> <script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script> <label class="md-header__button md-icon" for=__search> <svg xmlns=http://www.w3.org/2000/svgLine truncated
+12 -3
View File
@@ -24,15 +24,19 @@ Neither the parser nor the binary readers impose a limit on how deep the input m
Once a value has been parsed, operations that walk it recursively — serializing it with [`dump`](https://json.nlohmann.me/api/basic_json/dump/index.md), hashing it, copying it, comparing two values with `==`, `<`, or (in C++20) `<=>`, merging with [`update`](https://json.nlohmann.me/api/basic_json/update/index.md), applying a [`merge_patch`](https://json.nlohmann.me/api/basic_json/merge_patch/index.md), creating a patch with [`diff`](https://json.nlohmann.me/api/basic_json/diff/index.md) or [`merge_diff`](https://json.nlohmann.me/api/basic_json/merge_diff/index.md), converting it to another `basic_json` type, destroying it, and the binary writers (`to_cbor`, `to_msgpack`, ...) — descend at most [`JSON_RECURSION_DEPTH_LIMIT`](https://json.nlohmann.me/api/macros/json_recursion_depth_limit/index.md) levels on the call stack, 128 by default, and continue below that with an explicit stack on the heap. So the call stack does not grow with the nesting depth of the value, however deeply it is nested. ([`flatten`](https://json.nlohmann.me/api/basic_json/flatten/index.md), [`unflatten`](https://json.nlohmann.me/api/basic_json/unflatten/index.md), and [`to_bson`](https://json.nlohmann.me/api/basic_json/to_bson/index.md) never use the call stack for the nesting.)
The call stack still needs room for the levels that are recursed into, and the default limit assumes a stack of ordinary size. The stack that an operation needs is roughly proportional to the limit; with the default of 128 levels, the most demanding operation (`dump` in an unoptimized build) needed up to 288 KiB, and an optimized build needed 48 KiB or less, in measurements on macOS with arm64. The most demanding operation needed this much stack at the limits `0`, `32`, `128`, and `254`:
The call stack still needs room for the levels that are recursed into, and the default limit assumes a stack of ordinary size. The stack that an operation needs is roughly proportional to the limit; with the default of 128 levels, the most demanding operations (copying a value and converting it to another `basic_json` type, in an unoptimized build) needed up to 224 KiB, and an optimized build needed 48 KiB or less, in measurements on macOS with arm64. The most demanding operation needed this much stack at the limits `0`, `32`, `128`, and `254`:
| Stack needed, in KiB | limit 0 | limit 32 | limit 128 (default) | limit 254 |
| ------------------------- | ---------- | ---------- | ------------------- | --------- |
| unoptimized build (`-O0`) | 16 or less | 80 | 288 | 576 |
| unoptimized build (`-O0`) | 16 or less | 64 | 224 | 448 |
| optimized build (`-O2`) | 16 or less | 16 or less | 48 | 112 |
A thread with a smaller stack (a task of a real-time operating system, a fiber, or a thread of the musl C library, whose default stack is 128 KiB) can still overflow its stack on deeply nested input, which is why the limit can be lowered: define `JSON_RECURSION_DEPTH_LIMIT` to a smaller value, down to `0`, before including the library. Such a limit changes only the stack that is needed and the speed (values nested more deeply than the limit are walked more slowly), never a result. See the [documentation of the macro](https://json.nlohmann.me/api/macros/json_recursion_depth_limit/index.md) for the complete tables, the speed, and the rules for choosing a value. Destroying a value (its destructor) recurses over the same number of levels and then continues without the call stack, and needs 32 KiB or less at every limit.
Indented output and flattened keys grow with the depth
Some results are larger than the value by a factor of its nesting depth. [`dump`](https://json.nlohmann.me/api/basic_json/dump/index.md) with an `indent` of `n` (and likewise `operator<<` with `std::setw(n)` and [`basic_json_view::dump`](https://json.nlohmann.me/api/basic_json_view/dump/index.md)) writes up to `n` characters per nesting level in front of every line, and [`flatten`](https://json.nlohmann.me/api/basic_json/flatten/index.md) repeats the path of every value in its key. For the 80,001-byte array `[1,[1,...[1,1]...]]` with 20,000 levels, `dump(1)` returns 600 MB, `dump(4)` 2.4 GB, and the keys of `flatten()` hold 400 MB. A compact `dump()` without indentation stays the size of the value. If you pretty-print, log, or flatten untrusted input, limit its nesting depth while parsing, for example with a [parser callback](https://json.nlohmann.me/features/parsing/parser_callbacks/#recipe-max-nesting-depth-via-a-callback): with a limit of `d`, every line has at most `n * d` indentation characters, and every flattened key has at most `d` reference tokens. [`JSON_RECURSION_DEPTH_LIMIT`](https://json.nlohmann.me/api/macros/json_recursion_depth_limit/index.md) does not help here: it changes only how much of the call stack a walk uses, never its result, and it does not limit the depth that `parse()` accepts.
## Input size
The library does not limit the overall size of a JSON text; a value nested or wide enough will use memory proportional to the input. If you parse untrusted input of unbounded size, check the size of the file or stream yourself before — or while — handing it to `parse()`.
@@ -60,6 +64,10 @@ Parsing is not the only place invalid UTF-8 matters: a string that reached a `js
The JSON specification leaves the handling of repeated keys in an object up to the implementation, and this library does too: as described in [`object_t`](https://json.nlohmann.me/api/basic_json/object_t/#behavior), it is unspecified which of the values for a repeated key ends up in the parsed object. If your application must reject duplicate keys instead of silently resolving them one way or another, see the [parser callback recipe for rejecting duplicate keys](https://json.nlohmann.me/features/parsing/parser_callbacks/#recipe-rejecting-duplicate-object-keys).
## Objects with many keys in `ordered_json`
[`ordered_json`](https://json.nlohmann.me/api/ordered_json/index.md) keeps the members of an object in a vector in insertion order ([`ordered_map`](https://json.nlohmann.me/api/ordered_map/index.md)) and finds a key by searching all members. Parsing JSON text into an `ordered_json` avoids that search for objects with many keys and takes linear time. The binary readers ([`from_cbor`](https://json.nlohmann.me/api/basic_json/from_cbor/index.md), [`from_msgpack`](https://json.nlohmann.me/api/basic_json/from_msgpack/index.md), [`from_ubjson`](https://json.nlohmann.me/api/basic_json/from_ubjson/index.md), [`from_bjdata`](https://json.nlohmann.me/api/basic_json/from_bjdata/index.md), [`from_bson`](https://json.nlohmann.me/api/basic_json/from_bson/index.md), and [`from_bon8`](https://json.nlohmann.me/api/basic_json/from_bon8/index.md)) do not yet: reading an object of `n` keys into an `ordered_json` costs time proportional to `n²`. A flat object of 40,000 keys (about 300 KB of CBOR) takes about 1.3 s, against a few milliseconds as JSON text or into a `json` ([#6104](https://github.com/nlohmann/json/issues/6104)). `json` is not affected. If you read untrusted binary input into `ordered_json`, bound the input size more tightly, read it into a `json`, or reject objects with many keys in a [SAX handler](https://json.nlohmann.me/features/parsing/sax_interface/index.md).
## Numbers
A number whose value cannot be represented — for instance `1E1000`, which overflows `double` — is rejected while parsing as [`out_of_range.406`](https://json.nlohmann.me/home/exceptions/#jsonexceptionout_of_range406) rather than silently becoming infinity. An integer that is syntactically valid but does not fit the 64-bit integer types is not rejected; it is instead stored as a `double`, which may lose precision for very large values. See [number limits](https://json.nlohmann.me/features/types/number_handling/#number-limits) for the exact ranges and an example.
@@ -75,7 +83,8 @@ A [JSON Pointer](https://json.nlohmann.me/features/json_pointer/index.md) can co
## Checklist
- Wrap parsing in a `try`/`catch` block, or use `allow_exceptions=false`/`accept()` if your environment cannot use exceptions; never let `JSON_NOEXCEPTION`'s `abort()` be the first time you think about error handling.
- If the input's nesting depth matters to you, enforce your own limit with a [parser callback](https://json.nlohmann.me/features/parsing/parser_callbacks/#recipe-max-nesting-depth-via-a-callback) or a [SAX handler](https://json.nlohmann.me/features/parsing/sax_interface/index.md); the library bounds the call stack but not memory use.
- If the input's nesting depth matters to you (for example because you pretty-print, log, or flatten it), enforce your own limit with a [parser callback](https://json.nlohmann.me/features/parsing/parser_callbacks/#recipe-max-nesting-depth-via-a-callback) or a [SAX handler](https://json.nlohmann.me/features/parsing/sax_interface/index.md); the library bounds the call stack but not memory use.
- If you read untrusted binary input into `ordered_json`, mind that objects with many keys are [slow to read](#objects-with-many-keys-in-ordered_json).
- Bound the size of the input itself before parsing, independent of the library's own bounded allocations for binary format lengths.
- Decide up front how you want a string with invalid UTF-8 — from any source, not only parsing — to be serialized (`strict`, `replace`, or `ignore`), rather than discovering it from an uncaught `type_error.316`.
- For untrusted input in a binary format, pass `error_handler_t::strict` to the `from_*` function if the strings must be valid UTF-8; by default they are not checked (BON8 always checks).
+1 -1
View File
@@ -1 +1 @@
{"config":{"lang":["en"],"separator":"[\\s\\-\\.]","pipeline":["stopWordFilter"],"fields":{"title":{"boost":1000.0},"text":{"boost":1.0},"tags":{"boost":1000000.0}}},"docs":[{"location":"","title":"JSON for Modern C++","text":"<ul> <li> <p> Features</p> <p>Creating, parsing, accessing, and serializing JSON values, converting your own C++ types, JSON Pointer/Patch/Merge Patch, binary formats, zero-copy views, and more.</p> <p> Features</p> </li> <li> <p> Integration</p> <p>Add the library to your project via a single header, CMake, a package manager, or pkg-config.</p> <p> Integration</p> </li> <li> <p> API documentation</p> <p>The complete reference for <code>basic_json</code> and its member functions, types, and related classes, as well as for <code>json_document</code> and <code>json_view</code>.</p> <p> API documentation</p> </li> <li> <p> FAQ</p> <p>Answers to common questions and known surprises when using the library.</p> <p> FAQ</p> </li> <li> <p> Releases</p> <p>What changed in each release, with links to the relevant documentation.</p> <p> Releases</p> </li> <li> <p> Community</p> <p>The ecosystem, contribution guidelines, governance, and quality assurance around the project.</p> <p> Community</p> </li> </ul> <p> </p>"},{"location":"api/is_json_view/","title":"nlohmann::is_json_view","text":"<p>Defined in header <code>&lt;nlohmann/json_view.hpp&gt;</code></p> <pre><code>template&lt;typename T&gt;\nstruct is_json_view;\n</code></pre> <p>A type trait: <code>is_json_view&lt;T&gt;::value</code> is <code>true</code> if <code>T</code> is a <code>basic_json_view</code> of any <code>BasicJsonType</code> and any <code>view_mode</code> -- <code>json_view</code>, <code>json_editable_view</code>, <code>ordered_json_view</code>, ... -- and <code>false</code> otherwise, for <code>basic_json</code> as well.</p> <p>It is meant for constraining templates that accept views, in particular a <code>from_json()</code> that should read views directly: <code>get&lt;T&gt;()</code> on a view calls a <code>from_json()</code> with the view only if that <code>from_json()</code> accepts views but not arbitrary types.</p>"},{"location":"api/is_json_view/#template-parameters","title":"Template parameters","text":"<code>T</code> the type to check (without cv-qualifiers or references)"},{"location":"api/is_json_view/#notes","title":"Notes","text":"<p>A view is recognized by its member type <code>basic_json_type</code> (a <code>basic_json</code> specialization) and its <code>materialize()</code> returning that type, so the trait needs no declaration of the view class.</p>"},{"location":"api/is_json_view/#examples","title":"Examples","text":"Example <p>The example below shows the trait, and a <code>from_json()</code> constrained to <code>json</code> values and views: <code>get&lt;T&gt;()</code> on a view reads the view directly.</p> <pre><code>#include &lt;iostream&gt;\n#include &lt;type_traits&gt;\n#include &lt;nlohmann/json_view.hpp&gt;\n\nusing nlohmann::json;\n\nnamespace ns\n{\nstruct person\n{\n std::string name;\n int age = 0;\n};\n\n// reads json values and views (of any document type), but nothing else\ntemplate &lt; typename J, typename std::enable_if &lt; nlohmann::is_json_view&lt;J&gt;::value || std::is_same&lt;J, json&gt;::value, int &gt;::type = 0 &gt;\nvoid from_json(const J&amp; j, person&amp; p)\n{\n p.name = j.at(\"name\").template get&lt;std::string&gt;();\n p.age = j.at(\"age\").template get&lt;int&gt;();\n}\n} // namespace ns\n\nint main()\n{\n std::cout &lt;&lt; std::boolalpha\n &lt;&lt; nlohmann::is_json_view&lt;nlohmann::json_view&gt;::value &lt;&lt; ' '\n &lt;&lt; nlohmann::is_json_view&lt;nlohmann::ordered_json_editable_view&gt;::value &lt;&lt; ' '\n &lt;&lt; nlohmann::is_json_view&lt;json&gt;::value &lt;&lt; '\\n';\n\n const nlohmann::json_document doc = nlohmann::json_document::parse(R\"({\"name\": \"Ada\", \"age\": 36})\");\n const auto p = doc.root().get&lt;ns::person&gt;(); // reads the view, no json value is built\n std::cout &lt;&lt; p.name &lt;&lt; ' ' &lt;&lt; p.age &lt;&lt; '\\n';\n}\n</code></pre> <p>Output:</p> <pre><code>true true false\nAda 36\n</code></pre>"},{"location":"api/is_json_view/#see-also","title":"See also","text":"<ul> <li>basic_json_view - a handle to one value of a document</li> <li>get - which conversions read the view directly</li> <li>view_mode - read-only or editable</li> <li>Writing generic code - functions and <code>from_json()</code> for views</li> </ul>"},{"location":"api/is_json_view/#version-history","title":"Version history","text":"<p>Added in version 3.13.0 unreleased.</p>"},{"location":"api/json/","title":"nlohmann::json","text":"<pre><code>using json = basic_json&lt;&gt;;\n</code></pre> <p>This type is the default specialization of the basic_json class which uses the standard template types.</p>"},{"location":"api/json/#examples","title":"Examples","text":"Example <p>The example below demonstrates how Line truncated
{"config":{"lang":["en"],"separator":"[\\s\\-\\.]","pipeline":["stopWordFilter"],"fields":{"title":{"boost":1000.0},"text":{"boost":1.0},"tags":{"boost":1000000.0}}},"docs":[{"location":"","title":"JSON for Modern C++","text":"<ul> <li> <p> Features</p> <p>Creating, parsing, accessing, and serializing JSON values, converting your own C++ types, JSON Pointer/Patch/Merge Patch, binary formats, zero-copy views, and more.</p> <p> Features</p> </li> <li> <p> Integration</p> <p>Add the library to your project via a single header, CMake, a package manager, or pkg-config.</p> <p> Integration</p> </li> <li> <p> API documentation</p> <p>The complete reference for <code>basic_json</code> and its member functions, types, and related classes, as well as for <code>json_document</code> and <code>json_view</code>.</p> <p> API documentation</p> </li> <li> <p> FAQ</p> <p>Answers to common questions and known surprises when using the library.</p> <p> FAQ</p> </li> <li> <p> Releases</p> <p>What changed in each release, with links to the relevant documentation.</p> <p> Releases</p> </li> <li> <p> Community</p> <p>The ecosystem, contribution guidelines, governance, and quality assurance around the project.</p> <p> Community</p> </li> </ul> <p> </p>"},{"location":"api/is_json_view/","title":"nlohmann::is_json_view","text":"<p>Defined in header <code>&lt;nlohmann/json_view.hpp&gt;</code></p> <pre><code>template&lt;typename T&gt;\nstruct is_json_view;\n</code></pre> <p>A type trait: <code>is_json_view&lt;T&gt;::value</code> is <code>true</code> if <code>T</code> is a <code>basic_json_view</code> of any <code>BasicJsonType</code> and any <code>view_mode</code> -- <code>json_view</code>, <code>json_editable_view</code>, <code>ordered_json_view</code>, ... -- and <code>false</code> otherwise, for <code>basic_json</code> as well.</p> <p>It is meant for constraining templates that accept views, in particular a <code>from_json()</code> that should read views directly: <code>get&lt;T&gt;()</code> on a view calls a <code>from_json()</code> with the view only if that <code>from_json()</code> accepts views but not arbitrary types.</p>"},{"location":"api/is_json_view/#template-parameters","title":"Template parameters","text":"<code>T</code> the type to check (without cv-qualifiers or references)"},{"location":"api/is_json_view/#notes","title":"Notes","text":"<p>A view is recognized by its member type <code>basic_json_type</code> (a <code>basic_json</code> specialization) and its <code>materialize()</code> returning that type, so the trait needs no declaration of the view class.</p>"},{"location":"api/is_json_view/#examples","title":"Examples","text":"Example <p>The example below shows the trait, and a <code>from_json()</code> constrained to <code>json</code> values and views: <code>get&lt;T&gt;()</code> on a view reads the view directly.</p> <pre><code>#include &lt;iostream&gt;\n#include &lt;type_traits&gt;\n#include &lt;nlohmann/json_view.hpp&gt;\n\nusing nlohmann::json;\n\nnamespace ns\n{\nstruct person\n{\n std::string name;\n int age = 0;\n};\n\n// reads json values and views (of any document type), but nothing else\ntemplate &lt; typename J, typename std::enable_if &lt; nlohmann::is_json_view&lt;J&gt;::value || std::is_same&lt;J, json&gt;::value, int &gt;::type = 0 &gt;\nvoid from_json(const J&amp; j, person&amp; p)\n{\n p.name = j.at(\"name\").template get&lt;std::string&gt;();\n p.age = j.at(\"age\").template get&lt;int&gt;();\n}\n} // namespace ns\n\nint main()\n{\n std::cout &lt;&lt; std::boolalpha\n &lt;&lt; nlohmann::is_json_view&lt;nlohmann::json_view&gt;::value &lt;&lt; ' '\n &lt;&lt; nlohmann::is_json_view&lt;nlohmann::ordered_json_editable_view&gt;::value &lt;&lt; ' '\n &lt;&lt; nlohmann::is_json_view&lt;json&gt;::value &lt;&lt; '\\n';\n\n const nlohmann::json_document doc = nlohmann::json_document::parse(R\"({\"name\": \"Ada\", \"age\": 36})\");\n const auto p = doc.root().get&lt;ns::person&gt;(); // reads the view, no json value is built\n std::cout &lt;&lt; p.name &lt;&lt; ' ' &lt;&lt; p.age &lt;&lt; '\\n';\n}\n</code></pre> <p>Output:</p> <pre><code>true true false\nAda 36\n</code></pre>"},{"location":"api/is_json_view/#see-also","title":"See also","text":"<ul> <li>basic_json_view - a handle to one value of a document</li> <li>get - which conversions read the view directly</li> <li>view_mode - read-only or editable</li> <li>Writing generic code - functions and <code>from_json()</code> for views</li> </ul>"},{"location":"api/is_json_view/#version-history","title":"Version history","text":"<p>Added in version 3.13.0 unreleased.</p>"},{"location":"api/json/","title":"nlohmann::json","text":"<pre><code>using json = basic_json&lt;&gt;;\n</code></pre> <p>This type is the default specialization of the basic_json class which uses the standard template types.</p>"},{"location":"api/json/#examples","title":"Examples","text":"Example <p>The example below demonstrates how Line truncated