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

+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).