This commit is contained in:
nlohmann committed 2026-10-26 21:24:35 +00:00
1 parent 41c601a7d1
commit d2e264bd84
1400 files changed
+11859 -5440

No files matched your search

+3 -3
View File
@@ -1,7 +1,7 @@
<!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=author content="Niels Lohmann"><link href="https://json.nlohmann.me/features/performance/" rel="canonical"><link href=../object_order/ rel=prev><link href=../parsing/ rel=next><link rel=icon href=../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>Performance - JSON for Modern C++</title><link rel=stylesheet href=../../assets/stylesheets/main.ec1eaa64.min.css><link rel=stylesheet href=../../assets/stylesheets/palette.ab4e12ef.min.css><link rel="stylesheet" href="../../assets/external/fonts.googleapis.com/css.61a430c9.css"><style>:root{--md-text-font:"Roboto";--md-code-font:"JetBrains Mono"}</style><link rel=stylesheet href=../../css/custom.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=indigo data-md-color-accent=indigo> <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=#performance 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> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg> </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> Performance </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=indigo data-md-color-accent=indigo 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=indigo data-md-color-accent=indigo 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 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg> </label> <div class=md-searcLine 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=author content="Niels Lohmann"><link href="https://json.nlohmann.me/features/performance/" rel="canonical"><link href=../object_order/ rel=prev><link href=../parsing/ rel=next><link rel=icon href=../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>Performance - JSON for Modern C++</title><link rel=stylesheet href=../../assets/stylesheets/main.ec1eaa64.min.css><link rel=stylesheet href=../../assets/stylesheets/palette.ab4e12ef.min.css><link rel="stylesheet" href="../../assets/external/fonts.googleapis.com/css.61a430c9.css"><style>:root{--md-text-font:"Roboto";--md-code-font:"JetBrains Mono"}</style><link rel=stylesheet href=../../css/custom.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=indigo data-md-color-accent=indigo> <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=#performance 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> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg> </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> Performance </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=indigo data-md-color-accent=indigo 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=indigo data-md-color-accent=indigo 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 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg> </label> <div class=md-searcLine truncated
<span class=n>std</span><span class=o>::</span><span class=n>ifstream</span><span class=w> </span><span class=n>f</span><span class=p>(</span><span class=s>"example.json"</span><span class=p>);</span>
<span class=n>json</span><span class=w> </span><span class=n>j</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>parse</span><span class=p>(</span><span class=n>f</span><span class=p>);</span>
</code></pre></div> <p>Two macros switch the stream optimizations off without changing any result: <a href=../../api/macros/json_disable_stream_bulk_scan/ ><code>JSON_DISABLE_STREAM_BULK_SCAN</code></a> for stream buffers that do not follow the usual <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>streambuf</span></code> contract, and <a href=../../api/macros/json_disable_unlocked_file_io/ ><code>JSON_DISABLE_UNLOCKED_FILE_IO</code></a> for programs in which another thread must use the same <code class=highlight><span class=kt>FILE</span></code> object while it is parsed.</p> <p>For contiguous input with many non-<abbr title="American Standard Code for Information Interchange">ASCII</abbr> characters, <a href=../../api/macros/json_use_simdutf/ ><code>JSON_USE_SIMDUTF</code></a> can additionally speed up <abbr title="Unicode Transformation Format">UTF</abbr>-8 validation by using the <a href="https://github.com/simdutf/simdutf">simdutf</a> library instead of the built-in scalar validator; streaming inputs (files, <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>istream</span></code>, wide strings, user-defined adapters) always use the scalar path regardless of this macro.</p> <h2 id=large-documents>Large documents<a class=headerlink href=#large-documents title="Permanent link">&para;</a></h2> <p>Parsing always produces <abbr title="Simple API for XML">SAX</abbr> events internally; <a href=../../api/basic_json/parse/ ><code>parse</code></a> simply feeds them to a consumer that builds a complete <code>basic_json</code> value tree (a <abbr title="Document Object Model">DOM</abbr>) in memory. For documents too large to comfortably hold as a <abbr title="Document Object Model">DOM</abbr>, three alternatives avoid building it:</p> <ul> <li>Implement the <a href=../parsing/sax_interface/ ><abbr title="Simple API for XML">SAX</abbr> interface</a> directly and pass it to <a href=../../api/basic_json/sax_parse/ ><code>sax_parse</code></a>; only the parts of the input you choose to keep ever become <code>basic_json</code> values.</li> <li>Pass a <a href=../parsing/parser_callbacks/ >parser callback</a> to <code>parse</code>. This still builds a <abbr title="Document Object Model">DOM</abbr>, but the callback can discard finished elements as soon as they are handled, so memory usage stays bounded by one element (plus the unparsed remainder of the input) instead of the whole document -- see the <a href=../parsing/parser_callbacks/#recipe-streaming-a-large-homogeneous-array>recipe for streaming a large homogeneous array</a>.</li> <li>Parse into a <a href=../json_view/ ><code>json_document</code></a> (<code class=highlight><span class=o>&lt;</span><span class=n>nlohmann</span><span class=o>/</span><span class=n>json_view</span><span class=p>.</span><span class=n>hpp</span><span class=o>&gt;</span></code>) instead of a <code>basic_json</code>. It keeps the input text and builds a flat index of 16 bytes per value; strings and floating-point numbers are not copied, but read from the text when needed. Read-only <a href=../../api/basic_json_view/ >views</a> give the familiar element access, and only the parts you <a href=../../api/basic_json_view/materialize/ ><code>materialize()</code></a> become <code>basic_json</code> values. A document that borrows the text instead of owning a copy needs the text to outlive it; see <a href=../json_view/#choosing-between-json-ordered_json-the-sax-interface-and-json_view>choosing between <code>json</code>, the <abbr title="Simple API for XML">SAX</abbr> interface, and <code>json_view</code></a>.</li> </ul> <p>If the data is naturally record-oriented, consider <a href=../parsing/json_lines/ ><abbr title="JavaScript Object Notation">JSON</abbr> Lines</a> instead of one large <abbr title="JavaScript Object Notation">JSON</abbr> document: reading and parsing it line by line with <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>getline</span></code> means only one line's value is ever in memory at a time, and a malformed line does not invalidate lines already processed.</p> <h2 id=binary-formats>Binary formats<a class=headerlink href=#binary-formats title="Permanent link">&para;</a></h2> <p><abbr title="JavaScript Object Notation">JSON</abbr> text is not a compact format. If the data is only exchanged between programs (not read by humans), the <a href=../binary_formats/ >binary formats</a> -- <abbr title="Binary JData">BJData</abbr>, <abbr title="Binary Object Notation 8">BON8</abbr>, <abbr title="Binary JSON">BSON</abbr>, <abbr title="Concise Binary Object Representation">CBOR</abbr>, MessagePack, and <abbr title="Universal Binary JSON">UBJSON</abbr> -- encode the same values more compactly, which reduces both the bytes transferred and, for most of them, the work needed to parse them back. The <a href=../binary_formats/#sizes>size comparison</a> on that page, measured against minified <abbr titLine truncated
</code></pre></div> <p>Two macros switch the stream optimizations off without changing any result: <a href=../../api/macros/json_disable_stream_bulk_scan/ ><code>JSON_DISABLE_STREAM_BULK_SCAN</code></a> for stream buffers that do not follow the usual <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>streambuf</span></code> contract, and <a href=../../api/macros/json_disable_unlocked_file_io/ ><code>JSON_DISABLE_UNLOCKED_FILE_IO</code></a> for programs in which another thread must use the same <code class=highlight><span class=kt>FILE</span></code> object while it is parsed.</p> <p>For contiguous input with many non-<abbr title="American Standard Code for Information Interchange">ASCII</abbr> characters, <a href=../../api/macros/json_use_simdutf/ ><code>JSON_USE_SIMDUTF</code></a> can additionally speed up <abbr title="Unicode Transformation Format">UTF</abbr>-8 validation by using the <a href="https://github.com/simdutf/simdutf">simdutf</a> library instead of the built-in scalar validator; streaming inputs (files, <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>istream</span></code>, wide strings, user-defined adapters) always use the scalar path regardless of this macro.</p> <h2 id=large-documents>Large documents<a class=headerlink href=#large-documents title="Permanent link">&para;</a></h2> <p>Parsing always produces <abbr title="Simple API for XML">SAX</abbr> events internally; <a href=../../api/basic_json/parse/ ><code>parse</code></a> simply feeds them to a consumer that builds a complete <code>basic_json</code> value tree (a <abbr title="Document Object Model">DOM</abbr>) in memory. For documents too large to comfortably hold as a <abbr title="Document Object Model">DOM</abbr>, three alternatives avoid building it:</p> <ul> <li>Implement the <a href=../parsing/sax_interface/ ><abbr title="Simple API for XML">SAX</abbr> interface</a> directly and pass it to <a href=../../api/basic_json/sax_parse/ ><code>sax_parse</code></a>; only the parts of the input you choose to keep ever become <code>basic_json</code> values.</li> <li>Pass a <a href=../parsing/parser_callbacks/ >parser callback</a> to <code>parse</code>. This still builds a <abbr title="Document Object Model">DOM</abbr>, but the callback can discard finished elements as soon as they are handled, so memory usage stays bounded by one element (plus the unparsed remainder of the input) instead of the whole document -- see the <a href=../parsing/parser_callbacks/#recipe-streaming-a-large-homogeneous-array>recipe for streaming a large homogeneous array</a>.</li> <li>Parse into a <a href=../json_view/ ><code>json_document</code></a> (<code class=highlight><span class=o>&lt;</span><span class=n>nlohmann</span><span class=o>/</span><span class=n>json_view</span><span class=p>.</span><span class=n>hpp</span><span class=o>&gt;</span></code>) instead of a <code>basic_json</code>. It keeps the input text and builds a flat index of 16 bytes per value; strings and floating-point numbers are not copied, but read from the text when needed. Read-only <a href=../../api/basic_json_view/ >views</a> give the familiar element access, and only the parts you <a href=../../api/basic_json_view/materialize/ ><code>materialize()</code></a> become <code>basic_json</code> values. A document that borrows the text instead of owning a copy needs the text to outlive it; see <a href=../json_view/#choosing-between-json-ordered_json-the-sax-interface-and-json_view>choosing between <code>json</code>, the <abbr title="Simple API for XML">SAX</abbr> interface, and <code>json_view</code></a>.</li> </ul> <p>If the data is naturally record-oriented, consider <a href=../parsing/json_lines/ ><abbr title="JavaScript Object Notation">JSON</abbr> Lines</a> instead of one large <abbr title="JavaScript Object Notation">JSON</abbr> document: reading and parsing it line by line with <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>getline</span></code> means only one line's value is ever in memory at a time, and a malformed line does not invalidate lines already processed.</p> <h2 id=binary-formats>Binary formats<a class=headerlink href=#binary-formats title="Permanent link">&para;</a></h2> <p><abbr title="JavaScript Object Notation">JSON</abbr> text is not a compact format. If the data is only exchanged between programs (not read by humans), the <a href=../binary_formats/ >binary formats</a> -- <abbr title="Binary JData">BJData</abbr>, <abbr title="Binary Object Notation 8">BON8</abbr>, <abbr title="Binary JSON">BSON</abbr>, <abbr title="Concise Binary Object Representation">CBOR</abbr>, MessagePack, and <abbr title="Universal Binary JSON">UBJSON</abbr> -- encode the same values more compactly, which reduces both the bytes transferred and, for most of them, the work needed to parse them back. The <a href=../binary_formats/#sizes>size comparison</a> on that page, measured against minified <abbr titLine truncated
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;nlohmann/json_fwd.hpp&gt;</span>
<span class=k>class</span><span class=w> </span><span class=nc>my_type</span>
@@ -14,4 +14,4 @@
<span class=cp>#include</span><span class=w> </span><span class=cpf>"my_type.hpp"</span>
<span class=n>nlohmann</span><span class=o>::</span><span class=n>json</span><span class=w> </span><span class=nf>my_type::config</span><span class=p>()</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=p>{</span><span class=w> </span><span class=cm>/* ... */</span><span class=w> </span><span class=p>}</span>
</code></pre></div> <p>One caveat: ABI-affecting macros such as <code>JSON_DIAGNOSTICS</code> and <code>JSON_DIAGNOSTIC_POSITIONS</code> are encoded into the library's <a href=../namespace/#limitations>inline namespace name</a>. Every translation unit -- whether it includes <code>json_fwd.hpp</code> or the full header -- must define them the same way, or linking fails with undefined references instead of a compile error.</p> <p>If I/O support is not needed at all, <a href=../../api/macros/json_no_io/ ><code>JSON_NO_IO</code></a> excludes <code>&lt;cstdio&gt;</code>, <code>&lt;ios&gt;</code>, <code>&lt;iosfwd&gt;</code>, <code>&lt;istream&gt;</code>, and <code>&lt;ostream&gt;</code> outright and drops the <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>istream</span></code>/<code class=highlight><span class=kt>FILE</span><span class=o>*</span></code> <code>parse</code> overloads and <a href=../../api/operator_ltlt/ ><code>operator&lt;&lt;</code></a> that depend on them (<code>dump()</code> itself is unaffected, since it only returns a string); it exists for environments where those headers are unavailable (such as Intel SGX), and as a side effect those headers are then never processed by the compiler at all.</p> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li><a href=../../home/design_goals/ >Design goals</a> - why this library does not optimize for speed first</li> <li><a href=../../home/architecture/ >Architecture</a> - how input adapters, the lexer, and the serializer fit together</li> <li><a href=../parsing/ >Parsing</a> - the available parsing functions and inputs</li> <li><a href=../parsing/sax_interface/ ><abbr title="Simple API for XML">SAX</abbr> interface</a> - parse without building a <abbr title="Document Object Model">DOM</abbr></li> <li><a href=../json_view/ >Zero-copy <abbr title="JavaScript Object Notation">JSON</abbr> views</a> - parse into a flat index of the text and read it without building a <abbr title="Document Object Model">DOM</abbr></li> <li><a href=../binary_formats/ >Binary formats</a> - compact alternatives to <abbr title="JavaScript Object Notation">JSON</abbr> text</li> <li><a href=../object_order/ >Object Order</a> - <code>json</code> vs. <code>ordered_json</code> and other <code>ObjectType</code> choices</li> <li><a href=../types/template_parameters/ >Template Parameter Requirements</a> - custom container and allocator types</li> <li><a href=../macros/ >Supported macros</a> - overview of all configuration macros, including the diagnostics ones above</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 21, 2026 10:25:10 UTC">October 21, 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> <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-2Line truncated
</code></pre></div> <p>One caveat: <abbr title="Application Binary Interface">ABI</abbr>-affecting macros such as <code>JSON_DIAGNOSTICS</code> and <code>JSON_DIAGNOSTIC_POSITIONS</code> are encoded into the library's <a href=../namespace/#limitations>inline namespace name</a>. Every translation unit -- whether it includes <code>json_fwd.hpp</code> or the full header -- must define them the same way, or linking fails with undefined references instead of a compile error.</p> <p>If I/O support is not needed at all, <a href=../../api/macros/json_no_io/ ><code>JSON_NO_IO</code></a> excludes <code>&lt;cstdio&gt;</code>, <code>&lt;ios&gt;</code>, <code>&lt;iosfwd&gt;</code>, <code>&lt;istream&gt;</code>, and <code>&lt;ostream&gt;</code> outright and drops the <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>istream</span></code>/<code class=highlight><span class=kt>FILE</span><span class=o>*</span></code> <code>parse</code> overloads and <a href=../../api/operator_ltlt/ ><code>operator&lt;&lt;</code></a> that depend on them (<code>dump()</code> itself is unaffected, since it only returns a string); it exists for environments where those headers are unavailable (such as Intel <abbr title="Software Guard Extensions">SGX</abbr>), and as a side effect those headers are then never processed by the compiler at all.</p> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li><a href=../../home/design_goals/ >Design goals</a> - why this library does not optimize for speed first</li> <li><a href=../../home/architecture/ >Architecture</a> - how input adapters, the lexer, and the serializer fit together</li> <li><a href=../parsing/ >Parsing</a> - the available parsing functions and inputs</li> <li><a href=../parsing/sax_interface/ ><abbr title="Simple API for XML">SAX</abbr> interface</a> - parse without building a <abbr title="Document Object Model">DOM</abbr></li> <li><a href=../json_view/ >Zero-copy <abbr title="JavaScript Object Notation">JSON</abbr> views</a> - parse into a flat index of the text and read it without building a <abbr title="Document Object Model">DOM</abbr></li> <li><a href=../binary_formats/ >Binary formats</a> - compact alternatives to <abbr title="JavaScript Object Notation">JSON</abbr> text</li> <li><a href=../object_order/ >Object Order</a> - <code>json</code> vs. <code>ordered_json</code> and other <code>ObjectType</code> choices</li> <li><a href=../types/template_parameters/ >Template Parameter Requirements</a> - custom container and allocator types</li> <li><a href=../macros/ >Supported macros</a> - overview of all configuration macros, including the diagnostics ones above</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 25, 2026 11:07:13 UTC">October 25, 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> <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-31Line truncated
+10 -1
View File
@@ -51,13 +51,22 @@ If insertion order matters *and* an object routinely has many thousands of keys,
## Avoiding copies
- **Move instead of copy.** Constructing a `basic_json` from an existing one is [linear in its size](https://json.nlohmann.me/api/basic_json/basic_json/#complexity) for the copy constructor but [constant](https://json.nlohmann.me/api/basic_json/basic_json/#complexity) for the move constructor. The same applies to assigning a large `std::string`, `std::vector`, or other container into a value: pass it as `std::move(x)` rather than `x` whenever `x` is no longer needed afterwards.
- **Move instead of copy.** Constructing a `basic_json` from an existing one is [linear in its size](https://json.nlohmann.me/api/basic_json/basic_json/#complexity) for the copy constructor but [constant](https://json.nlohmann.me/api/basic_json/basic_json/#complexity) for the move constructor. The same applies to assigning a large `std::string`, `std::vector`, or other container into a value: pass it as `std::move(x)` rather than `x` whenever `x` is no longer needed afterwards. Since version 3.13.0 unreleased, converting an rvalue container (`json j = std::move(vec);`) moves the elements instead of copying them; the source is then left in a valid but unspecified state.
- **Access without copying.** [`get<T>()`](https://json.nlohmann.me/api/basic_json/get/index.md) returns a copy of the stored value converted to `T`. When a reference or pointer to the value already stored inside the `basic_json` is enough, [`get_ref()`](https://json.nlohmann.me/api/basic_json/get_ref/index.md) and [`get_ptr()`](https://json.nlohmann.me/api/basic_json/get_ptr/index.md) access it directly: both pages state, word for word, "No copies are made." -- at the cost of that reference or pointer becoming invalid once the underlying value changes.
- **Iterate by reference.** `basic_json::iterator::operator*()` returns a `reference` (an alias for `basic_json&`), but a range-based for loop with a by-value loop variable (`for (auto el : j)`) still copies each element, because plain `auto` drops the reference. Write `for (const auto& el : j)` (or `auto&` for a mutable loop), and use [`items()`](https://json.nlohmann.me/api/basic_json/items/index.md) the same way when the key is needed too -- its own examples use `for (auto& el : j.items())`.
- **Construct in place.** [`emplace_back()`](https://json.nlohmann.me/api/basic_json/emplace_back/index.md) (arrays, amortized constant time) and [`emplace()`](https://json.nlohmann.me/api/basic_json/emplace/index.md) (objects, logarithmic in the size of the container for `json`) forward their arguments directly to a `basic_json` constructor, rather than requiring a temporary value to be constructed and then copied or moved in. [`push_back()`](https://json.nlohmann.me/api/basic_json/push_back/index.md) has an rvalue overload (`push_back(basic_json&&)`) for a value that already exists: `j.push_back(std::move(value))` moves it in instead of copying it.
- **Skip the bounds check when it is redundant.** [`at()`](https://json.nlohmann.me/api/basic_json/at/index.md) and [`operator[]`](https://json.nlohmann.me/api/basic_json/operator%5B%5D/index.md) have the same complexity (constant for a valid array index, logarithmic for an object key in `json`) -- the difference is that `at()` additionally checks the key or index and throws if it is invalid, while `operator[]` does not (see [unchecked access](https://json.nlohmann.me/features/element_access/unchecked_access/index.md) and [checked access](https://json.nlohmann.me/features/element_access/checked_access/index.md)). Prefer `operator[]` when the surrounding code has already established that the access is valid.
- **Reserve array capacity.** `basic_json` has no public `reserve()`, but when building a large array incrementally with a known final size, [`get_ref()`](https://json.nlohmann.me/api/basic_json/get_ref/index.md) exposes the underlying `array_t` so it can be reserved directly -- see ["reserving array capacity"](https://json.nlohmann.me/features/element_access/unchecked_access/#performance-reserving-array-capacity) for the one-line recipe.
## Memory
- **A value is small, its content is on the heap.** A `basic_json` is 16 bytes on a 64-bit platform (a type tag and a union). Strings, arrays, objects, and binary values are allocated on the heap and owned by the value. Destroying the value frees everything it owns.
- **Copies are deep.** After `json b = a;`, changing `b` does not change `a`, and both own their memory. Copying a large value therefore doubles its memory; see [Avoiding copies](#avoiding-copies). `auto x = j["key"];` is a copy, `auto& x = j["key"];` is not.
- **A moved-from value is `null`.** After `json c = std::move(a);` the value `a` is `null` and owns nothing.
- **Reading does not require a tree.** If you only read the data, parse it into a [`json_document`](https://json.nlohmann.me/features/json_view/index.md) (`<nlohmann/json_view.hpp>`, added in version 3.13.0 unreleased) instead of a `basic_json`. It stores 16 bytes per value, does not copy floating-point numbers or strings without escape sequences out of the text, and creates no `basic_json` value except for the parts you [`materialize()`](https://json.nlohmann.me/api/basic_json_view/materialize/index.md). A document that borrows the text needs the text to outlive it; see [Zero-copy JSON views](https://json.nlohmann.me/features/json_view/index.md).
- **Containers keep their capacity.** `clear()` and `erase()` on an array remove the elements, but the underlying `std::vector` keeps its allocated capacity, like `std::vector::clear` does. To give the memory back, assign a new value (`j = json::array();`) or destroy the value.
- **Freed memory does not always go back to the operating system.** The library returns memory to the allocator (`std::allocator` by default, or the [one you configured](https://json.nlohmann.me/features/types/template_parameters/index.md)). Whether the process size shrinks then depends on the allocator and the platform, as for any C++ program. A process that parses a large document and drops it is not leaking if its resident size stays high; run it under a tool such as [Valgrind](https://valgrind.org) or the sanitizers to tell a leak from retained memory.
## Serialization
[`dump()`](https://json.nlohmann.me/api/basic_json/dump/index.md) with the default `indent = -1` selects "the most compact representation" (word for word from the page); any non-negative `indent` pretty-prints instead, which is more readable but produces more bytes and more work. `dump()` builds and returns a complete `string_t` containing the whole serialization. [`operator<<`](https://json.nlohmann.me/api/operator_ltlt/index.md) writes directly to a `std::ostream` instead, through the same serializer, but without ever materializing that intermediate string -- so if the destination is a stream (a file, or `std::cout`), `os << j;` avoids the allocation and copy that `os << j.dump();` would incur for large values.