This commit is contained in:
nlohmann committed 2026-09-15 20:47:46 +00:00
1 parent 7b7abfd224
commit db9042b6ac
306 files changed
+4213 -781

No files matched your search

+5 -4
View File
@@ -1,4 +1,4 @@
<!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/types/" rel="canonical"><link href=../trailing_commas/ rel=prev><link href=number_handling/ rel=next><link rel=icon href=../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>Types - 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=#types 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> Types </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-search data-md-componLine 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/types/" rel="canonical"><link href=../trailing_commas/ rel=prev><link href=number_handling/ rel=next><link rel=icon href=../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>Types - 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=#types 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> Types </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-search data-md-componLine truncated
class value_t {
&lt;&lt;enumeration&gt;&gt;
@@ -49,7 +49,8 @@ basic_json .. value_t</code></pre> <h2 id=template-arguments>Template arguments<
<span class=w> </span><span class=k>class</span><span class=w> </span><span class=nc>NumberFloatType</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=kt>double</span><span class=p>,</span>
<span class=w> </span><span class=k>template</span><span class=o>&lt;</span><span class=k>typename</span><span class=w> </span><span class=nc>U</span><span class=o>&gt;</span><span class=w> </span><span class=k>class</span><span class=w> </span><span class=nc>AllocatorType</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>allocator</span><span class=p>,</span>
<span class=w> </span><span class=k>template</span><span class=o>&lt;</span><span class=k>typename</span><span class=w> </span><span class=nc>T</span><span class=p>,</span><span class=w> </span><span class=k>typename</span><span class=w> </span><span class=nc>SFINAE</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=kt>void</span><span class=o>&gt;</span><span class=w> </span><span class=k>class</span><span class=w> </span><span class=nc>JSONSerializer</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>adl_serializer</span><span class=p>,</span>
<span class=w> </span><span class=k>class</span><span class=w> </span><span class=nc>BinaryType</span><span class=w> </span><span class=o>=</span><span class=w> </span><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=kt>uint8_t</span><span class=o>&gt;</span>
<span class=w> </span><span class=k>class</span><span class=w> </span><span class=nc>BinaryType</span><span class=w> </span><span class=o>=</span><span class=w> </span><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=kt>uint8_t</span><span class=o>&gt;</span><span class=p>,</span>
<span class=w> </span><span class=k>class</span><span class=w> </span><span class=nc>CustomBaseClass</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=kt>void</span>
<span class=o>&gt;</span>
<span class=k>class</span><span class=w> </span><span class=nc>basic_json</span><span class=p>;</span>
</code></pre></div> <p>Type <code>json</code> is an alias for <code>basic_json&lt;&gt;</code> and uses the default types.</p> <p>From the template arguments, the following types are derived:</p> <div class=highlight><pre><span></span><code><span class=k>using</span><span class=w> </span><span class=n>object_comparator_t</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>less</span><span class=o>&lt;&gt;</span><span class=p>;</span>
@@ -67,7 +68,7 @@ basic_json .. value_t</code></pre> <h2 id=template-arguments>Template arguments<
<span class=k>using</span><span class=w> </span><span class=n>number_float_t</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>NumberFloatType</span><span class=p>;</span>
<span class=k>using</span><span class=w> </span><span class=n>binary_t</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>nlohmann</span><span class=o>::</span><span class=n>byte_container_with_subtype</span><span class=o>&lt;</span><span class=n>BinaryType</span><span class=o>&gt;</span><span class=p>;</span>
</code></pre></div> <h2 id=objects>Objects<a class=headerlink href=#objects title="Permanent link">&para;</a></h2> <p><a href="https://tools.ietf.org/html/rfc8259"><abbr title="Request for Comments">RFC</abbr> 8259</a> describes <abbr title="JavaScript Object Notation">JSON</abbr> objects as follows:</p> <blockquote> <p>An object is an unordered collection of zero or more name/value pairs, where a name is a string and a value is a string, number, boolean, null, object, or array.</p> </blockquote> <h3 id=default-type>Default type<a class=headerlink href=#default-type title="Permanent link">&para;</a></h3> <p>With the default values for <em>ObjectType</em> (<code>std::map</code>), <em>StringType</em> (<code>std::string</code>), and <em>AllocatorType</em> (<code>std::allocator</code>), the default value for <code>object_t</code> is:</p> <div class=highlight><pre><span></span><code><span class=n>std</span><span class=o>::</span><span class=n>map</span><span class=o>&lt;</span>
</code></pre></div> <p>Not every type can be passed for these template arguments: the library uses the resulting types in ways that imply a number of requirements, for instance that <code>StringType</code> is <code>char</code>-based or that <code>ArrayType</code> is vector-like. These requirements are collected in <a href=template_parameters/ >Template Parameter Requirements</a>.</p> <h2 id=objects>Objects<a class=headerlink href=#objects title="Permanent link">&para;</a></h2> <p><a href="https://tools.ietf.org/html/rfc8259"><abbr title="Request for Comments">RFC</abbr> 8259</a> describes <abbr title="JavaScript Object Notation">JSON</abbr> objects as follows:</p> <blockquote> <p>An object is an unordered collection of zero or more name/value pairs, where a name is a string and a value is a string, number, boolean, null, object, or array.</p> </blockquote> <h3 id=default-type>Default type<a class=headerlink href=#default-type title="Permanent link">&para;</a></h3> <p>With the default values for <em>ObjectType</em> (<code>std::map</code>), <em>StringType</em> (<code>std::string</code>), and <em>AllocatorType</em> (<code>std::allocator</code>), the default value for <code>object_t</code> is:</p> <div class=highlight><pre><span></span><code><span class=n>std</span><span class=o>::</span><span class=n>map</span><span class=o>&lt;</span>
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=p>,</span><span class=w> </span><span class=c1>// key_type</span>
<span class=w> </span><span class=n>basic_json</span><span class=p>,</span><span class=w> </span><span class=c1>// value_type</span>
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>less</span><span class=o>&lt;&gt;</span><span class=p>,</span><span class=w> </span><span class=c1>// key_compare</span>
@@ -80,4 +81,4 @@ basic_json .. value_t</code></pre> <h2 id=template-arguments>Template arguments<
<span class=w> </span><span class=n>basic_json</span><span class=p>,</span><span class=w> </span><span class=c1>// value_type</span>
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>allocator</span><span class=o>&lt;</span><span class=n>basic_json</span><span class=o>&gt;</span><span class=w> </span><span class=c1>// allocator_type</span>
<span class=o>&gt;</span>
</code></pre></div> <h3 id=limits_1>Limits<a class=headerlink href=#limits_1 title="Permanent link">&para;</a></h3> <p><a href="https://tools.ietf.org/html/rfc8259"><abbr title="Request for Comments">RFC</abbr> 8259</a> specifies:</p> <blockquote> <p>An implementation may set limits on the maximum depth of nesting.</p> </blockquote> <p>In this class, the array's limit of nesting is not explicitly constrained. However, a maximum depth of nesting may be introduced by the compiler or runtime environment. A theoretical limit can be queried by calling the <code>max_size</code> function of a <abbr title="JavaScript Object Notation">JSON</abbr> array.</p> <h3 id=storage_2>Storage<a class=headerlink href=#storage_2 title="Permanent link">&para;</a></h3> <p>Arrays are stored as pointers in a <code>basic_json</code> type. That is, for any access to array values, a pointer of type <code>array_t*</code> must be dereferenced.</p> <h2 id=strings>Strings<a class=headerlink href=#strings title="Permanent link">&para;</a></h2> <p><a href="https://tools.ietf.org/html/rfc8259"><abbr title="Request for Comments">RFC</abbr> 8259</a> describes <abbr title="JavaScript Object Notation">JSON</abbr> strings as follows:</p> <blockquote> <p>A string is a sequence of zero or more Unicode characters.</p> </blockquote> <p>Unicode values are split by the <abbr title="JavaScript Object Notation">JSON</abbr> class into byte-sized characters during deserialization.</p> <h3 id=default-type_2>Default type<a class=headerlink href=#default-type_2 title="Permanent link">&para;</a></h3> <p>With the default values for <em>StringType</em> (<code>std::string</code>), the default value for <code>string_t</code> is <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>string</span></code>.</p> <h3 id=encoding>Encoding<a class=headerlink href=#encoding title="Permanent link">&para;</a></h3> <p>Strings are stored in <abbr title="Unicode Transformation Format">UTF</abbr>-8 encoding. Therefore, functions like <code>std::string::size()</code> or <code>std::string::length()</code> return the number of <strong>bytes</strong> in the string rather than the number of characters or glyphs.</p> <h3 id=string-comparison>String comparison<a class=headerlink href=#string-comparison title="Permanent link">&para;</a></h3> <p><a href="https://tools.ietf.org/html/rfc8259"><abbr title="Request for Comments">RFC</abbr> 8259</a> states:</p> <blockquote> <p>Software implementations are typically required to test names of object members for equality. Implementations that transform the textual representation into sequences of Unicode code units and then perform the comparison numerically, code unit by code unit are interoperable in the sense that implementations will agree in all cases on equality or inequality of two strings. For example, implementations that compare strings with escaped characters unconverted may incorrectly find that <code>"a\\b"</code> and <code>"a\u005Cb"</code> are not equal.</p> </blockquote> <p>This implementation is interoperable as it does compare strings code unit by code unit.</p> <h3 id=storage_3>Storage<a class=headerlink href=#storage_3 title="Permanent link">&para;</a></h3> <p>String values are stored as pointers in a <code>basic_json</code> type. That is, for any access to string values, a pointer of type <code>string_t*</code> must be dereferenced.</p> <h2 id=booleans>Booleans<a class=headerlink href=#booleans title="Permanent link">&para;</a></h2> <p><a href="https://tools.ietf.org/html/rfc8259"><abbr title="Request for Comments">RFC</abbr> 8259</a> implicitly describes a boolean as a type which differentiates the two literals <code>true</code> and <code>false</code>.</p> <h3 id=default-type_3>Default type<a class=headerlink href=#default-type_3 title="Permanent link">&para;</a></h3> <p>With the default values for <em>BooleanType</em> (<code class=highlight><span class=kt>bool</span></code>), the default value for <code>boolean_t</code> is <code class=highlight><span class=kt>bool</span></code>.</p> <h3 id=storage_4>Storage<a class=headerlink href=#storage_4 title="Permanent link">&para;</a></h3> <p>Boolean values are stored directly inside a <code>basic_json</code> type.</p> <h2 id=numbers>Numbers<a class=headerlink href=#numbers title="Permanent link">&para;</a></h2> <p>See the <a href=number_handling/ >number handling</a> article for a detailed discussion on how numbers are handled by this library.</p> <p><a href="https://tools.ietf.org/html/rfc8259"><abbr title="Request for Comments">RFC</abbr> 8259</a> describes numbers as follows:</p> <blockquote> <p>The representation of numbers is similar to that used in most programming languages. A number is represented in base 10 using decimal digits. It contains an integer component that may be prefixed with an optional minus sign, which may be followed by a fraction part and/or an exponent part. Leading zeros are not allowed. (...) Numeric values that cannot be reprLine truncated
</code></pre></div> <h3 id=limits_1>Limits<a class=headerlink href=#limits_1 title="Permanent link">&para;</a></h3> <p><a href="https://tools.ietf.org/html/rfc8259"><abbr title="Request for Comments">RFC</abbr> 8259</a> specifies:</p> <blockquote> <p>An implementation may set limits on the maximum depth of nesting.</p> </blockquote> <p>In this class, the array's limit of nesting is not explicitly constrained. However, a maximum depth of nesting may be introduced by the compiler or runtime environment. A theoretical limit can be queried by calling the <code>max_size</code> function of a <abbr title="JavaScript Object Notation">JSON</abbr> array.</p> <h3 id=storage_2>Storage<a class=headerlink href=#storage_2 title="Permanent link">&para;</a></h3> <p>Arrays are stored as pointers in a <code>basic_json</code> type. That is, for any access to array values, a pointer of type <code>array_t*</code> must be dereferenced.</p> <h2 id=strings>Strings<a class=headerlink href=#strings title="Permanent link">&para;</a></h2> <p><a href="https://tools.ietf.org/html/rfc8259"><abbr title="Request for Comments">RFC</abbr> 8259</a> describes <abbr title="JavaScript Object Notation">JSON</abbr> strings as follows:</p> <blockquote> <p>A string is a sequence of zero or more Unicode characters.</p> </blockquote> <p>Unicode values are split by the <abbr title="JavaScript Object Notation">JSON</abbr> class into byte-sized characters during deserialization.</p> <h3 id=default-type_2>Default type<a class=headerlink href=#default-type_2 title="Permanent link">&para;</a></h3> <p>With the default values for <em>StringType</em> (<code>std::string</code>), the default value for <code>string_t</code> is <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>string</span></code>.</p> <h3 id=encoding>Encoding<a class=headerlink href=#encoding title="Permanent link">&para;</a></h3> <p>Strings are stored in <abbr title="Unicode Transformation Format">UTF</abbr>-8 encoding. Therefore, functions like <code>std::string::size()</code> or <code>std::string::length()</code> return the number of <strong>bytes</strong> in the string rather than the number of characters or glyphs.</p> <h3 id=string-comparison>String comparison<a class=headerlink href=#string-comparison title="Permanent link">&para;</a></h3> <p><a href="https://tools.ietf.org/html/rfc8259"><abbr title="Request for Comments">RFC</abbr> 8259</a> states:</p> <blockquote> <p>Software implementations are typically required to test names of object members for equality. Implementations that transform the textual representation into sequences of Unicode code units and then perform the comparison numerically, code unit by code unit are interoperable in the sense that implementations will agree in all cases on equality or inequality of two strings. For example, implementations that compare strings with escaped characters unconverted may incorrectly find that <code>"a\\b"</code> and <code>"a\u005Cb"</code> are not equal.</p> </blockquote> <p>This implementation is interoperable as it does compare strings code unit by code unit.</p> <h3 id=storage_3>Storage<a class=headerlink href=#storage_3 title="Permanent link">&para;</a></h3> <p>String values are stored as pointers in a <code>basic_json</code> type. That is, for any access to string values, a pointer of type <code>string_t*</code> must be dereferenced.</p> <h2 id=booleans>Booleans<a class=headerlink href=#booleans title="Permanent link">&para;</a></h2> <p><a href="https://tools.ietf.org/html/rfc8259"><abbr title="Request for Comments">RFC</abbr> 8259</a> implicitly describes a boolean as a type which differentiates the two literals <code>true</code> and <code>false</code>.</p> <h3 id=default-type_3>Default type<a class=headerlink href=#default-type_3 title="Permanent link">&para;</a></h3> <p>With the default values for <em>BooleanType</em> (<code class=highlight><span class=kt>bool</span></code>), the default value for <code>boolean_t</code> is <code class=highlight><span class=kt>bool</span></code>.</p> <h3 id=storage_4>Storage<a class=headerlink href=#storage_4 title="Permanent link">&para;</a></h3> <p>Boolean values are stored directly inside a <code>basic_json</code> type.</p> <h2 id=numbers>Numbers<a class=headerlink href=#numbers title="Permanent link">&para;</a></h2> <p>See the <a href=number_handling/ >number handling</a> article for a detailed discussion on how numbers are handled by this library.</p> <p><a href="https://tools.ietf.org/html/rfc8259"><abbr title="Request for Comments">RFC</abbr> 8259</a> describes numbers as follows:</p> <blockquote> <p>The representation of numbers is similar to that used in most programming languages. A number is represented in base 10 using decimal digits. It contains an integer component that may be prefixed with an optional minus sign, which may be followed by a fraction part and/or an exponent part. Leading zeros are not allowed. (...) Numeric values that cannot be reprLine truncated
+4 -1
View File
@@ -79,7 +79,8 @@ template<
class NumberFloatType = double,
template<typename U> class AllocatorType = std::allocator,
template<typename T, typename SFINAE = void> class JSONSerializer = adl_serializer,
class BinaryType = std::vector<std::uint8_t>
class BinaryType = std::vector<std::uint8_t>,
class CustomBaseClass = void
>
class basic_json;
```
@@ -106,6 +107,8 @@ using number_float_t = NumberFloatType;
using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
```
Not every type can be passed for these template arguments: the library uses the resulting types in ways that imply a number of requirements, for instance that `StringType` is `char`-based or that `ArrayType` is vector-like. These requirements are collected in [Template Parameter Requirements](https://json.nlohmann.me/features/types/template_parameters/index.md).
## Objects
[RFC 8259](https://tools.ietf.org/html/rfc8259) describes JSON objects as follows:
+2 -2
View File
@@ -1,4 +1,4 @@
<!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/types/number_handling/" rel="canonical"><link href=../ rel=prev><link href=../../../integration/ rel=next><link rel=icon href=../../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>Number Handling - 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=#number-handling 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> Number Handling </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.5Line 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/types/number_handling/" rel="canonical"><link href=../ rel=prev><link href=../template_parameters/ rel=next><link rel=icon href=../../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>Number Handling - 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=#number-handling 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> Number Handling </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 9Line truncated
<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>f</span><span class=p>;</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=n>j</span><span class=w> </span><span class=o>&lt;&lt;</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
</code></pre></div> yields <code class=highlight><span class=mf>0.30000001192092896</span></code>.</li> </ul> <p>All examples here can be reproduced by passing the original double value to</p> <div class=highlight><pre><span></span><code><span class=n>std</span><span class=o>::</span><span class=n>printf</span><span class=p>(</span><span class=s>"%.*g</span><span class=se>\n</span><span class=s>"</span><span class=p>,</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>numeric_limits</span><span class=o>&lt;</span><span class=kt>double</span><span class=o>&gt;::</span><span class=n>max_digits10</span><span class=p>,</span><span class=w> </span><span class=n>double_value</span><span class=p>);</span>
@@ -54,4 +54,4 @@ val=nan
<span class=p>}</span>
</code></pre></div> <p>Note this approach also has the advantage that it can react on non-numerical <abbr title="JavaScript Object Notation">JSON</abbr> value types such as strings.</p> <p>(Example taken from <a href="https://github.com/nlohmann/json/issues/777#issuecomment-459968458">#777</a>.)</p> </div> <h3 id=determine-number-types>Determine number types<a class=headerlink href=#determine-number-types title="Permanent link">&para;</a></h3> <p>As the example in <a href=#number-conversion>Number conversion</a> shows, there are different functions to determine the type of the stored number:</p> <ul> <li><a href=../../../api/basic_json/is_number/ ><code>is_number()</code></a> returns <code class=highlight><span class=nb>true</span></code> for any number type</li> <li><a href=../../../api/basic_json/is_number_integer/ ><code>is_number_integer()</code></a> returns <code class=highlight><span class=nb>true</span></code> for signed and unsigned integers</li> <li><a href=../../../api/basic_json/is_number_unsigned/ ><code>is_number_unsigned()</code></a> returns <code class=highlight><span class=nb>true</span></code> for unsigned integers only</li> <li><a href=../../../api/basic_json/is_number_float/ ><code>is_number_float()</code></a> returns <code class=highlight><span class=nb>true</span></code> for floating-point numbers</li> <li><a href=../../../api/basic_json/type_name/ ><code>type_name()</code></a> returns <code class=highlight><span class=s>"number"</span></code> for any number type</li> <li><a href=../../../api/basic_json/type/ ><code>type()</code></a> returns a different enumerator of <a href=../../../api/basic_json/value_t/ ><code>value_t</code></a> for all number types</li> </ul> <table> <thead> <tr> <th>function</th> <th>unsigned integer</th> <th>signed integer</th> <th>floating-point</th> <th>string</th> </tr> </thead> <tbody> <tr> <td><a href=../../../api/basic_json/is_number/ ><code>is_number()</code></a></td> <td><code class=highlight><span class=nb>true</span></code></td> <td><code class=highlight><span class=nb>true</span></code></td> <td><code class=highlight><span class=nb>true</span></code></td> <td><code class=highlight><span class=nb>false</span></code></td> </tr> <tr> <td><a href=../../../api/basic_json/is_number_integer/ ><code>is_number_integer()</code></a></td> <td><code class=highlight><span class=nb>true</span></code></td> <td><code class=highlight><span class=nb>true</span></code></td> <td><code class=highlight><span class=nb>false</span></code></td> <td><code class=highlight><span class=nb>false</span></code></td> </tr> <tr> <td><a href=../../../api/basic_json/is_number_unsigned/ ><code>is_number_unsigned()</code></a></td> <td><code class=highlight><span class=nb>true</span></code></td> <td><code class=highlight><span class=nb>false</span></code></td> <td><code class=highlight><span class=nb>false</span></code></td> <td><code class=highlight><span class=nb>false</span></code></td> </tr> <tr> <td><a href=../../../api/basic_json/is_number_float/ ><code>is_number_float()</code></a></td> <td><code class=highlight><span class=nb>false</span></code></td> <td><code class=highlight><span class=nb>false</span></code></td> <td><code class=highlight><span class=nb>true</span></code></td> <td><code class=highlight><span class=nb>false</span></code></td> </tr> <tr> <td><a href=../../../api/basic_json/type_name/ ><code>type_name()</code></a></td> <td><code class=highlight><span class=s>"number"</span></code></td> <td><code class=highlight><span class=s>"number"</span></code></td> <td><code class=highlight><span class=s>"number"</span></code></td> <td><code class=highlight><span class=s>"string"</span></code></td> </tr> <tr> <td><a href=../../../api/basic_json/type/ ><code>type()</code></a></td> <td><code>number_unsigned</code></td> <td><code>number_integer</code></td> <td><code>number_float</code></td> <td><code>string</code></td> </tr> </tbody> </table> <h3 id=template-number-types>Template number types<a class=headerlink href=#template-number-types title="Permanent link">&para;</a></h3> <p>The number types can be changed with template parameters.</p> <table> <thead> <tr> <th>position</th> <th>number type</th> <th>default type</th> <th>possible values</th> </tr> </thead> <tbody> <tr> <td>5</td> <td>signed integers</td> <td><code class=highlight><span class=n>std</span><span class=o>::</span><span class=kt>int64_t</span></code></td> <td><code class=highlight><span class=n>std</span><span class=o>::</span><span class=kt>int32_t</span></code>, <code class=highlight><span class=n>std</span><span class=o>::</span><span class=kt>int16_t</span></code>, etc.</td> </tr> <tr> <td>6</td> <td>unsigned integers</td> <td><code class=highlight><span class=n>std</span><span class=o>::</span><span class=kt>uint64_t</span></code></td> <td><code class=highlight><span class=n>std</span><span class=o>::</span><span class=kt>uint32_t</span></code>, <code class=highlight><span class=n>std</span><span class=o>::</spanLine truncated
<span class=hll><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=kt>int64_t</span><span class=p>,</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=kt>uint64_t</span><span class=p>,</span><span class=w> </span><span class=kt>long</span><span class=w> </span><span class=kt>double</span><span class=o>&gt;</span><span class=p>;</span>
</span></code></pre></div> <p>Note values should then be parsed with <code>json_ld::parse</code> rather than <code>json::parse</code> as the latter would parse floating-point values to <code class=highlight><span class=kt>double</span></code> before then converting them to <code class=highlight><span class=kt>long</span><span class=w> </span><span class=kt>double</span></code>.</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="September 14, 2026 19:19:41 UTC">September 14, 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-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.linkedin.com/in/nielslohmann/" target="_blank" rel="noopener" title="www.linkedin.com" class="md-social__link"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 448 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="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3M135.4 416H69V202.2h66.5V416zM102.2 96a38.5 38.5 0 1 1 0 77 38.5 38.5 0 1 1 0-77m282.1 320h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9z"/></svg> </a> <a href="https://www.xing.com/profile/Niels_Lohmann" target="_blank" rel="noopener" title="www.xing.com" class="md-social__link"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 384 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 OFLLine truncated
</span></code></pre></div> <p>Note values should then be parsed with <code>json_ld::parse</code> rather than <code>json::parse</code> as the latter would parse floating-point values to <code class=highlight><span class=kt>double</span></code> before then converting them to <code class=highlight><span class=kt>long</span><span class=w> </span><span class=kt>double</span></code>.</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="September 15, 2026 18:46:37 UTC">September 15, 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-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.linkedin.com/in/nielslohmann/" target="_blank" rel="noopener" title="www.linkedin.com" class="md-social__link"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 448 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="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3M135.4 416H69V202.2h66.5V416zM102.2 96a38.5 38.5 0 1 1 0 77 38.5 38.5 0 1 1 0-77m282.1 320h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9z"/></svg> </a> <a href="https://www.xing.com/profile/Niels_Lohmann" target="_blank" rel="noopener" title="www.xing.com" class="md-social__link"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 384 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 OFLLine truncated
+747
View File
@@ -0,0 +1,747 @@
# Template Parameter Requirements
Class [`basic_json`](../../api/basic_json/index.md) is configurable through eleven template parameters. The library
never formally states what a type passed for one of these parameters has to provide -- the requirements are implied by
the way the library uses the resulting [`object_t`](../../api/basic_json/object_t.md),
[`array_t`](../../api/basic_json/array_t.md), [`string_t`](../../api/basic_json/string_t.md), etc. This page collects
these requirements so they do not have to be discovered by trial and error. Each section lists the concrete types
that are known to work for that parameter and the ones that do not, checked against Boost 1.83, Abseil 20250127.0,
Folly, EASTL 3.21, `ankerl::unordered_dense`, `phmap`, `gtl`, `robin_hood`, `tsl::ordered_map`, and Qt 6.
## How to read this page
Requirements are split into two groups:
- **Always required** -- needed to instantiate `basic_json` at all, or needed by functions that virtually every program
uses (construction, element access, [`dump`](../../api/basic_json/dump.md)).
- **Required for ...** -- only needed when a particular part of the API is instantiated. Member function templates are
only instantiated when they are used, so a type may be perfectly usable even though it does not satisfy these
requirements, as long as the corresponding functions are never called.
!!! warning "Requirements are not checked"
Three requirements are checked with a `#!cpp static_assert`: the array iterator category, the width of
[`BinaryType`](#binarytype)'s `value_type`, and [`NumberUnsignedType`](#numberintegertype-and-numberunsignedtype)
being at least as wide as [`NumberIntegerType`](#numberintegertype-and-numberunsignedtype). The rest are not
diagnosed with dedicated error messages, and violating most of them results in a compiler error somewhere inside
the library. Four violations are not caught at compile time at all:
- A [`StringType`](#stringtype) whose `data()` is not null-terminated compiles and silently misparses numbers,
because the lexer hands the buffer to `#!cpp std::strtoull`/`#!cpp std::strtoll`/`#!cpp std::strtod`.
- A stateful [`AllocatorType`](#allocatortype) compiles and silently ignores its state: allocation, deallocation,
and [`get_allocator()`](../../api/basic_json/get_allocator.md) each use a different default-constructed instance.
- The two [cross-specialization conversions](#cross-specialization-conversions) below. These abort on an assertion
in a normal build, and only fail silently under `#!cpp NDEBUG`.
## Overview
| Template parameter | Default | Notable substitutes |
|-------------------------------------------------------------------|-----------------------------------|-----------------------------------------------------------------------|
| [`ObjectType`](#objecttype) | `std::map` | [`nlohmann::ordered_map`](../../api/ordered_map.md), Abseil hash maps |
| [`ArrayType`](#arraytype) | `std::vector` | `#!cpp std::deque` |
| [`StringType`](#stringtype) | `std::string` | `std::string`-like types over `char` |
| [`BooleanType`](#booleantype) | `bool` | none worth using |
| [`NumberIntegerType`](#numberintegertype-and-numberunsignedtype) | `std::int64_t` | any signed integer type |
| [`NumberUnsignedType`](#numberintegertype-and-numberunsignedtype) | `std::uint64_t` | any unsigned integer type at least as wide as `NumberIntegerType` |
| [`NumberFloatType`](#numberfloattype) | `double` | `float` (`long double`: no binary formats) |
| [`AllocatorType`](#allocatortype) | `std::allocator` | stateless allocators |
| [`JSONSerializer`](#jsonserializer) | `adl_serializer` | serializers with the same interface |
| [`BinaryType`](#binarytype) | `#!cpp std::vector<std::uint8_t>` | `#!cpp std::vector<char>` |
| [`CustomBaseClass`](#custombaseclass) | `void` | any default-constructible class |
!!! warning "Third-party containers and incomplete types"
`object_t` is instantiated inside the definition of `basic_json` -- it is probed for a `key_compare` member to
form [`object_comparator_t`](../../api/basic_json/object_comparator_t.md) -- i.e. while `basic_json` is still an
incomplete type. `#!cpp std::map` is required by the standard to support incomplete mapped types; most
third-party maps are not, and inspecting the mapped type at class scope (for instance with
`#!cpp std::is_trivially_move_assignable`) makes them unusable as `ObjectType`, no matter how their template
arguments are adapted. This rules out `absl::btree_map`, `phmap::btree_map`, `gtl::btree_map`,
`robin_hood::unordered_node_map`, `folly::F14FastMap`, and `eastl::hash_map`.
`array_t` is only *named* in the class definition and is not instantiated until `basic_json` is complete, so an
`ArrayType` that inspects its value type at class scope is generally fine -- `boost::container::small_vector` and
`static_vector` both reject incomplete value types yet work here. `absl::InlinedVector` is the exception: the
`#!cpp std::is_trivially_move_assignable<basic_json>` it evaluates while instantiating itself re-enters the
library's own trait machinery mid-instantiation.
!!! note "Folly requires C++20"
Folly's headers use `#!cpp consteval` and `#!cpp std::type_identity`, so any `basic_json` specialization that
names a Folly type has to be compiled as C++20 or later, whatever the rest of the library supports.
## `ObjectType`
`ObjectType` is instantiated as
```cpp
using object_t = ObjectType<StringType, // key_type
basic_json, // mapped_type
default_object_comparator_t, // key_compare
AllocatorType<std::pair<const StringType,
basic_json>>>; // allocator_type
```
i.e., the template arguments follow the order and meaning of `std::map`.
### Always required
- The template must be usable with **four** type arguments in the order shown above. The third argument is a
**comparator**; containers that expect something else in this position (e.g., a hash function) need an alias template
or wrapper -- see [Notes](#notes).
- An optional member type `key_compare`. If it is present it becomes
[`object_comparator_t`](../../api/basic_json/object_comparator_t.md); otherwise
[`default_object_comparator_t`](../../api/basic_json/default_object_comparator_t.md) is used.
- Member types `key_type`, `mapped_type`, `value_type`, and `iterator`.
- `value_type` must behave like `#!cpp std::pair<const key_type, mapped_type>`; the library accesses `.first` and
`.second` on it.
- `iterator` must be default-constructible and satisfy
[LegacyBidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator). The type returned
by `cbegin()`/`cend()` must satisfy the same requirements.
- Constructors: default, copy, move, and from an iterator range `(first, last)`.
- Member functions `begin()`, `end()`, `cbegin()`, `cend()`, `empty()`, `size()`, `max_size()`, `clear()`,
`find(key)`, `count(key)`, `emplace(key, value)`, `insert(value_type)`, `insert(first, last)`, `operator[](key)`,
`erase(iterator)`, and `erase(first, last)`. `erase(iterator)` may return the following iterator or `#!cpp void`;
in the latter case the library computes the successor itself, before erasing.
- `erase(key)` is **optional**: if the container does not provide one, the library falls back to `find(key)` followed
by `erase(iterator)`.
- `at(key)` is required only by [`to_ubjson`](../../api/basic_json/to_ubjson.md) and
[`to_bjdata`](../../api/basic_json/to_bjdata.md), but every container tried here provides it.
- `emplace` and `insert(value_type)` must return `#!cpp std::pair<iterator, bool>` and must have **unique-key**
semantics; multimaps cannot be used.
- The type must be swappable (via `std::swap` or an ADL `swap`).
- The comparison operators `==` and `<`; `!=`, `<=`, `>`, and `>=` are derived from them. Where the library uses
three-way comparison (C++20), `==` and `<=>` are required **instead** -- the six two-way operators do not satisfy
it. They implement [`basic_json`'s comparison operators](../../api/basic_json/operator_eq.md).
### Required for heterogeneous key lookup
The overloads of [`at`](../../api/basic_json/at.md), [`operator[]`](../../api/basic_json/operator%5B%5D.md),
[`find`](../../api/basic_json/find.md), [`contains`](../../api/basic_json/contains.md),
[`count`](../../api/basic_json/count.md), [`erase`](../../api/basic_json/erase.md), and
[`value`](../../api/basic_json/value.md) that accept a key type other than `object_t::key_type` require
- a **transparent** comparator, i.e. [`object_comparator_t`](../../api/basic_json/object_comparator_t.md) has a member
type `is_transparent` (this is why the default comparator is `#!cpp std::less<>` since C++14), and
- corresponding heterogeneous `find`, `count`, `erase`, and `operator[]` overloads on the container.
### Notes
#### `std::unordered_map` needs an adapter
`#!cpp std::unordered_map` cannot be passed directly: its third template parameter is a hash function, but
`basic_json` passes a comparator in that position. An alias template or wrapper that restores the expected argument
order makes it usable:
```cpp
template<class Key, class T, class IgnoredCompare, class Allocator>
struct unordered_map_object
: std::unordered_map<Key, T, std::hash<Key>, std::equal_to<Key>, Allocator>
{
using base_t = std::unordered_map<Key, T, std::hash<Key>, std::equal_to<Key>, Allocator>;
using base_t::base_t;
};
using unordered_json = nlohmann::basic_json<unordered_map_object>;
```
Whether `#!cpp std::unordered_map` can be instantiated at all depends on the standard library: `object_t` is formed
while `basic_json` is still incomplete (see the warning above), and libstdc++ 9 needs the size of the mapped type to
instantiate the hash map's node type, so the adapter does not compile there. Newer libstdc++ versions, and the hash
maps listed below, do not have that problem.
The adapter above works verbatim for Abseil's, Boost's, `phmap`'s and `gtl`'s hash maps, which all place the hash
function third and take a `#!cpp std::pair<const Key, T>` allocator fifth. Two need a different adapter:
- `ankerl::unordered_dense` expects an allocator over `#!cpp std::pair<Key, T>` (non-const key), so the allocator has
to be rebound to that or dropped.
- `robin_hood`'s fifth parameter is the non-type `MaxLoadFactor100`, so its adapter must drop the allocator entirely.
None of these hash maps defines `key_compare`, so all of them additionally rely on `object_comparator_t` falling back
to [`default_object_comparator_t`](../../api/basic_json/default_object_comparator_t.md); see
[`object_comparator_t`](../../api/basic_json/object_comparator_t.md).
#### Abseil hash maps
`absl::flat_hash_map` and `absl::node_hash_map` tolerate an incomplete value type, but they take a hash function as
their third template argument. The same adapter as for `#!cpp std::unordered_map` makes them usable:
```cpp
template<class Key, class T, class IgnoredCompare, class Allocator>
struct flat_hash_object
: absl::flat_hash_map<Key, T, absl::Hash<Key>, std::equal_to<Key>, Allocator>
{
using base_t = absl::flat_hash_map<Key, T, absl::Hash<Key>, std::equal_to<Key>, Allocator>;
using base_t::base_t;
};
using flat_hash_json = nlohmann::basic_json<flat_hash_object>;
```
`absl::node_hash_map` keeps references to the mapped values valid across insertions; `absl::flat_hash_map` does not,
which makes it behave like [`ordered_json`](../../api/ordered_json.md) with respect to
[iterator invalidation](../../api/basic_json/index.md#iterator-invalidation). Both expose a `capacity()` member
function, so [`JSON_DIAGNOSTICS`](../../api/macros/json_diagnostics.md) treats them conservatively and keeps the
parent pointers correct either way.
#### Iteration order
The library never relies on the container's iteration order for correctness; it does determine the order in which
object keys are serialized by [`dump`](../../api/basic_json/dump.md) and visited by
[`items`](../../api/basic_json/items.md). See [Object Order](../object_order.md).
#### `capacity()` marks a container as insertion-ordered
With [`JSON_DIAGNOSTICS`](../../api/macros/json_diagnostics.md) enabled, the library detects insertion-ordered maps by
probing for a `capacity()` member function (`nlohmann::ordered_map` inherits it from `std::vector`) and refreshes all
parent pointers after every insertion. An `ObjectType` that happens to have a `capacity()` member is therefore treated
conservatively -- this is correct, but slower.
#### Key order and duplicate keys
The library does not sort or de-duplicate keys itself; the behavior described in
[`object_t`](../../api/basic_json/object_t.md) is entirely the behavior of the chosen container.
!!! tip "Reference implementation"
`docs/mkdocs/docs/examples/custom_object_type.hpp` wraps a private `#!cpp std::map` and satisfies every
requirement above. It does not define `key_compare`, so `object_comparator_t` falls back to
[`default_object_comparator_t`](../../api/basic_json/default_object_comparator_t.md) -- a good starting point for
a custom `ObjectType`.
```cpp
--8<-- "examples/custom_object_type.hpp"
```
??? example "Compiling and using it"
```cpp
--8<-- "examples/custom_object_type.cpp"
```
Output:
```json
--8<-- "examples/custom_object_type.output"
```
### Compatible containers
| Container | Notes |
|----------------------------------------------------------------------------------|-------------------------------------------------------------------------------|
| `#!cpp std::map` (default) | |
| [`nlohmann::ordered_map`](../../api/ordered_map.md) | used by [`ordered_json`](../../api/ordered_json.md); keeps insertion order |
| [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map) | keeps insertion order; adapter puts `fifo_map_compare` in the comparator slot |
| `boost::container::map`, `boost::container::flat_map` | no adapter needed |
| `#!cpp std::unordered_map` | through the adapter above; not with libstdc++ 9, see the note |
| `boost::unordered_map`, `boost::unordered_flat_map`, `boost::unordered_node_map` | through the adapter above |
| `absl::flat_hash_map`, `absl::node_hash_map` | through the adapter above; `flat_hash_map` moves mapped values on rehash |
| `phmap::flat_hash_map`, `phmap::node_hash_map`, `gtl::flat_hash_map` | through the adapter above |
| `ankerl::unordered_dense::map` and `segmented_map` | adapter must rebind or drop the allocator |
| `robin_hood::unordered_flat_map` | adapter must drop the allocator |
| `folly::F14NodeMap` | through the adapter above; requires C++20, see the note above |
| `folly::sorted_vector_map` | alias must drop the allocator, whose value type it disagrees on |
### Containers that cannot be used
| Container | Reason |
|--------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|
| `absl::btree_map`, `phmap::btree_map`, `gtl::btree_map` | require a complete mapped type |
| `robin_hood::unordered_node_map`, `folly::F14FastMap`, `eastl::hash_map` | require a complete mapped type |
| `eastl::map` | EASTL iterators do not work with `#!cpp std::iterator_traits` |
| `tsl::ordered_map` | its iterators expose the mapped value as `#!cpp const` |
| `QMap` | no `value_type` member type |
| `QHash` | its `value_type` is the mapped type rather than a key/value pair, and its iterators dereference to the mapped value |
| `#!cpp std::multimap`, `#!cpp std::unordered_multimap` | `emplace` does not return `#!cpp std::pair<iterator, bool>` |
## `ArrayType`
`ArrayType` is instantiated as
```cpp
using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
```
### Always required
- The template must be usable with **two** type arguments (value type and allocator).
- Member types `value_type` and `iterator`.
- Constructors: default, copy, and move; and from an iterator range `(first, last)`.
- Member functions `begin()`, `end()`, `cbegin()`, `cend()`, `empty()`, `size()`, `max_size()`, `clear()`,
`operator[](size_type)`, `back()`, `push_back()`, `emplace_back()`, `pop_back()`, `resize()`,
`insert()` (single element, count, and range), `erase(pos)`, and `erase(first, last)`.
`basic_json::insert(pos, initializer_list)` goes through the range overload, so no initializer-list `insert` is
needed. `at(size_type)` is **not** required: [`basic_json::at(size_type)`](../../api/basic_json/at.md) checks the
index itself and then uses `operator[]`.
- `iterator` must be default-constructible, and it as well as the type returned by `cbegin()`/`cend()` must satisfy
[LegacyRandomAccessIterator](https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator).
A `#!cpp static_assert` only checks for
[LegacyBidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator), but
[`dump`](../../api/basic_json/dump.md) (`cend() - 1`),
[`erase(idx)`](../../api/basic_json/erase.md) (`begin() + idx`), and the random-access operations of
[`basic_json::iterator`](../../api/basic_json/begin.md) require random access.
- The comparison operators, as for [`ObjectType`](#objecttype): `==` and `<`, or `==` and `<=>` under C++20.
### Required for individual functions
- A member type `value_type`, for [`to_bson`](../../api/basic_json/to_bson.md) of an array.
- A constructor from `(count, value)`, for
[`basic_json(size_type, const basic_json&)`](../../api/basic_json/basic_json.md).
- Swappability, via `#!cpp std::swap` or an ADL `swap`, for [`swap(array_t&)`](../../api/basic_json/swap.md).
!!! note "`capacity()` is optional"
With [`JSON_DIAGNOSTICS`](../../api/macros/json_diagnostics.md) enabled, the library reads `array_t::capacity()`
to find out whether adding an element reallocated the array and moved its elements, which would invalidate the
parent pointers. An array type without a `capacity()` member function is handled conservatively: the parent
pointers of all elements are refreshed after every insertion, which makes adding *n* elements cost O(*n*²). Only
diagnostics builds pay this; without them `capacity()` is never called.
!!! tip "Reference implementation"
`docs/mkdocs/docs/examples/custom_array_type.hpp` wraps a private `#!cpp std::vector` and satisfies every
requirement above -- a good starting point for a custom `ArrayType`.
```cpp
--8<-- "examples/custom_array_type.hpp"
```
??? example "Compiling and using it"
```cpp
--8<-- "examples/custom_array_type.cpp"
```
Output:
```json
--8<-- "examples/custom_array_type.output"
```
### Compatible containers
| Container | Notes |
|---------------------------------------------------------|-------------------------------------------------------------------------------------------|
| `#!cpp std::vector` (default) | |
| `#!cpp std::deque` | references survive appends, but not insertions elsewhere; see the `capacity()` note above |
| `#!cpp std::pmr::vector` | through an alias, as the allocator comes from `AllocatorType` instead |
| `boost::container::vector`, `deque`, `devector` | |
| `boost::container::stable_vector` | the only one tried that keeps references valid across *every* insertion |
| `boost::container::small_vector`, `folly::small_vector` | through an alias that fixes the inline capacity |
| `boost::container::static_vector` | through the same kind of alias, for arrays that stay within the fixed capacity |
| `folly::fbvector` | requires C++20, see the note above |
### Containers that cannot be used
| Container | Reason |
|-------------------------------------|-----------------------------------------------------------------------------------------------|
| `#!cpp std::list` | no `operator[]`, and no random-access iterators |
| `eastl::vector`, `QList`, `QVector` | no `max_size()`; they handle the incomplete value type fine |
| `absl::InlinedVector` | requires a complete value type, see the note above |
| `absl::FixedArray` | the size is fixed at construction, so `resize`, `push_back`, `insert` and `erase` are missing |
## `StringType`
`StringType` is used **both** for JSON string values and for the keys of JSON objects
(`string_t` and `object_t::key_type`).
### Always required
- A member type `value_type` that is one byte wide and `char`-compatible. The library stores and processes UTF-8
encoded `char` data and hands `data()` to `#!cpp std::strtoull`/`#!cpp std::strtoll`.
`#!cpp std::wstring`, `#!cpp std::u16string`, and `#!cpp std::u32string` are **not** valid choices; see the FAQ on
[wide string handling](../../home/faq.md#wide-string-handling).
- Constructors: default, copy, move, from `#!cpp const char*` (which must not be `#!cpp explicit`), from
`#!cpp (const char*, size_type)`, and from `#!cpp (size_type, char)`; and copy or move assignment.
- Member functions `size()`, `clear()`, `resize(n, c)`, `data()`, `push_back(char)`, and `operator[]`
(const and non-const, returning references). `c_str()` and `back()` are **not** required.
- `data()` must return a pointer to a contiguous, **null-terminated** buffer -- the parser hands it to
`#!cpp std::strtoull`. A type whose `data()` is not null-terminated does not fail to compile; it silently
misparses numbers.
- `append(const char*, size_type)`, used by [`dump`](../../api/basic_json/dump.md), and `append(const StringType&)`,
used by the CBOR reader for indefinite-length strings. The library's internal string concatenation additionally has
to append a `#!cpp char` and a `#!cpp const char*`; for each it selects between `append(arg)`, `#!cpp operator+=`,
`append(first, last)`, and `append(data, size)`.
- The comparison operator `==` against another `StringType`, and `<` for use as a key of the chosen
[`ObjectType`](#objecttype) (with the default comparator, `#!cpp std::less<>` must be able to compare two
`StringType` values, and a `StringType` with the key types used for lookup). `!=` is never applied to a
`StringType`, and `==` against `#!cpp const char*` is resolved by the implicit `#!cpp const char*` constructor.
### Required for the binary formats
- `resize(n)`, used by the readers to make room for a block of bytes.
- Non-const `operator[]`, into which the readers `#!cpp std::memcpy` those bytes. A non-`#!cpp const` `data()` would
serve just as well, but `#!cpp std::string` has only had one since C++17, and the library still supports C++11.
### Required for JSON Pointer, `flatten`, and `diff`
- A static member `npos` and the member function `find_first_of(char, size_type)` -- together with `data()`,
`reserve(n)`, and `append(const char*, size_type)` they implement the escaping and unescaping of reference tokens
described in RFC 6901. Neither `find(const StringType&, size_type)`, nor `substr(pos, count)`, nor
`replace(pos, count, const StringType&)` is required.
- `empty()`.
- `begin()` and `end()` -- used by
[`operator[](const json_pointer&)`](../../api/basic_json/operator%5B%5D.md) to decide whether a reference token
denotes an array index.
### Required for other functionality
| Functionality | Additional requirement |
|-----------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [`diff`](../../api/basic_json/diff.md), [`items`](../../api/basic_json/items.md), [`std::hash`](../../api/basic_json/std_hash.md) | conversion of a `#!cpp std::size_t` to `StringType`: either assignability from the result of `#!cpp std::to_string`, or an ADL overload `#!cpp void int_to_string(StringType&, std::size_t)` |
| [`std::hash<basic_json>`](../../api/basic_json/std_hash.md) | additionally a specialization of `#!cpp std::hash<StringType>` |
| [`to_bson`](../../api/basic_json/to_bson.md) | `find(value_type)` and `npos` |
| [`parse`](../../api/basic_json/parse.md) from a `string_t` | the input adapters must accept it; otherwise pass a character range |
| `#!cpp operator<<(std::ostream&, const json_pointer&)` | streamability to `#!cpp std::ostream` |
| exception messages | `data()` and `size()`, or `begin()` and `end()` |
### Compatible types
| Type | Notes |
|-----------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `#!cpp std::string` (default) | |
| `#!cpp std::basic_string` with a custom **stateless** allocator | |
| `#!cpp std::pmr::string` | see the warning below before relying on the memory resource |
| `boost::container::string` | needs a user-supplied `#!cpp std::hash` specialization (Boost provides `boost::hash` instead) |
| `folly::fbstring` | requires C++20, see the note above |
| `eastl::string` | needs a user-supplied `#!cpp std::hash` and an ADL `int_to_string` (it is not assignable from a `#!cpp std::string`); [`parse`](../../api/basic_json/parse.md) does not accept it directly -- pass a character range or a `#!cpp std::string` |
| a custom string class in a user-defined namespace | if the requirements above are met |
### Types that cannot be used
| Type | Reason |
|----------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
| `#!cpp std::wstring`, `#!cpp std::u16string`, `#!cpp std::u32string` | the character type is not one byte wide |
| `#!cpp std::u8string` | one byte wide, but `#!cpp char8_t` is not `#!cpp char`-compatible |
| `absl::Cord` | no `value_type`, and the storage is not contiguous |
| `QString` | no `append(const char*, size_type)`; its `QChar` is also two bytes wide, though that is never diagnosed |
!!! warning "A `std::pmr::string` mostly does not use the memory resource you choose"
`basic_json` cannot be given an allocator or a memory resource. `AllocatorType` is default-constructed at every
allocation and has to be stateless (see [`AllocatorType`](#allocatortype)), and string values the library creates
are constructed with their own default allocator. So:
- Every string the library itself produces -- from [`parse`](../../api/basic_json/parse.md), from
[`dump`](../../api/basic_json/dump.md), or by default construction -- allocates from
`#!cpp std::pmr::get_default_resource()`.
- **Copying** an arena-backed string into a value silently drops its memory resource: the copy lands on the
default resource, because `#!cpp std::pmr::polymorphic_allocator` does not propagate on copy construction.
Nothing warns about this.
- **Moving** one in does keep it, and later growth still allocates from that arena -- but it does not survive a
copy of the enclosing `basic_json`.
- Passing `#!cpp std::pmr::polymorphic_allocator` as `AllocatorType` does not work around any of this; it does
not compile.
Apart from moving a string in, the only way to redirect these allocations is the process-global
`#!cpp std::pmr::set_default_resource()`.
!!! tip "Reference implementation"
`docs/mkdocs/docs/examples/custom_string_type.hpp` wraps a private `#!cpp std::string` and satisfies every
requirement above -- a good starting point for a custom `StringType`. The unit test
`tests/src/unit-alt-string.cpp` contains a more thorough variant, `alt_string`, exercised against a larger part
of the API.
```cpp
--8<-- "examples/custom_string_type.hpp"
```
??? example "Compiling and using it"
```cpp
--8<-- "examples/custom_string_type.cpp"
```
Output:
```json
--8<-- "examples/custom_string_type.output"
```
## `BooleanType`
`boolean_t` is stored **directly** inside `basic_json`, as a member of an anonymous union.
### Always required
- A literal type that is trivially default-constructible, trivially copyable, and trivially destructible; otherwise the
union's special member functions are deleted.
- **Implicitly** convertible from `#!cpp bool` -- an `#!cpp explicit` constructor is not enough, because the
`to_json` overload for a custom `BooleanType` is constrained on `#!cpp std::is_convertible` -- and contextually
convertible to `#!cpp bool` (here an `#!cpp explicit operator bool` is fine).
- Comparison operators `==`, `!=`, `<`, `<=`, `>`, `>=` (or `<=>`).
- Convertible from and to `#!cpp bool` through the serializer, because
[`get<bool>()`](../../api/basic_json/get.md) is used internally.
There is little reason to use anything other than `#!cpp bool` here.
### Compatible types
`#!cpp bool` is the only usable choice. Another trivially copyable type that is implicitly convertible to and from
`#!cpp bool` -- `#!cpp std::uint8_t`, say -- does compile, and JSON booleans still round-trip, but the type then
serves as both `boolean_t` and an ordinary integer: `basic_json` can no longer be constructed or assigned from a
`#!cpp std::uint8_t` at all (the boolean and unsigned-integer `to_json` overloads become ambiguous), and
[`get<std::uint8_t>()`](../../api/basic_json/get.md) on a number throws
[`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) instead of returning the value.
## `NumberIntegerType` and `NumberUnsignedType`
Both types are stored **directly** inside `basic_json`'s union.
### Always required
- `#!cpp std::is_integral` must be satisfied: `NumberIntegerType` must be a **signed** integer type,
`NumberUnsignedType` an **unsigned** integer type. Class types are not supported -- among others, the constructors
taking integer values are constrained on `#!cpp std::is_integral`.
- Trivially default-constructible, trivially copyable, and trivially destructible (union member).
- `#!cpp std::numeric_limits` must be specialized for both types.
- `NumberUnsignedType` must be able to represent the absolute value of every `NumberIntegerType` value; serialization
of negative numbers converts the value to `NumberUnsignedType`. A `#!cpp static_assert` requires it to be at least as
wide as `NumberIntegerType`, which is what that amounts to for the standard integer types.
- Both types must fit into the internal 64-character number buffer used by
[`dump`](../../api/basic_json/dump.md), which is the case for all standard integer types.
- [`std::hash<basic_json>`](../../api/basic_json/std_hash.md) additionally requires `#!cpp std::hash` specializations.
### Notes
The number types influence what the parser accepts: an integer literal that does not round-trip through the chosen type
is stored as [`number_float_t`](../../api/basic_json/number_float_t.md) instead. Choosing types narrower than 64 bits
therefore silently changes parse results rather than raising an error. See
[Number Handling](number_handling.md) for details.
### Compatible types
| Type pair | Support |
|----------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `#!cpp std::int64_t` / `#!cpp std::uint64_t` (default) | full |
| `#!cpp std::int32_t` / `#!cpp std::uint32_t`, `#!cpp long long` / `#!cpp unsigned long long` | full; narrower types change which literals the parser can represent |
| any other pair of standard signed/unsigned integer types | full |
| class types, enumerations | not usable; `#!cpp std::is_integral` must hold |
| `#!cpp bool`, or a type already used for another member of the union | not usable; `#!cpp std::is_integral<bool>` is in fact `#!cpp true`, but the `get_impl_ptr` overloads for `boolean_t`, `number_integer_t`, `number_unsigned_t` and `number_float_t` would collide |
## `NumberFloatType`
`number_float_t` is stored **directly** inside `basic_json`'s union.
### Always required
- Trivially default-constructible, trivially copyable, and trivially destructible (union member).
- `#!cpp std::numeric_limits` must be specialized; `max_digits10` is used to size the conversion.
- `#!cpp std::isfinite` must be applicable to the type.
### Required for parsing and serialization
`NumberFloatType` must be one of `#!cpp float`, `#!cpp double`, or `#!cpp long double`:
- The [parser](../parsing/index.md) converts number literals with `#!cpp std::strtof`, `#!cpp std::strtod`, or
`#!cpp std::strtold`; the library provides overloads for exactly these three types.
- [`dump`](../../api/basic_json/dump.md) falls back to `#!cpp std::snprintf` with the `%g` and `%Lg` conversion
specifiers, for which the library likewise provides only `#!cpp double` and `#!cpp long double` overloads
(`#!cpp float` is promoted to `#!cpp double`).
If `#!cpp std::numeric_limits<NumberFloatType>` describes an IEEE 754 binary32 or binary64 number, `dump` uses the
Grisu2 algorithm, which produces the shortest representation that round-trips. Otherwise the `snprintf` fallback with
`max_digits10` digits is used.
### Required for the binary formats
`NumberFloatType` must be `#!cpp float` or `#!cpp double`. The writers for
[CBOR, MessagePack, UBJSON, BJData, and BSON](../binary_formats/index.md) map a floating-point value onto an IEEE 754
binary32 or binary64 field and have no encoding for `#!cpp long double`.
### Compatible types
| Type | Support |
|--------------------------|-----------------------------------------------------------------------------------------------------------------------|
| `#!cpp double` (default) | full; short round-trip output through Grisu2 |
| `#!cpp float` | full; short round-trip output through Grisu2 |
| `#!cpp long double` | `dump` and `parse` only; the binary format writers do not compile, as they only handle IEEE 754 binary32 and binary64 |
| any other type | not usable |
## `AllocatorType`
`AllocatorType` is instantiated with **one** argument, for each of `object_t`, `array_t`, `string_t`, `binary_t`,
`basic_json`, and `#!cpp std::pair<const StringType, basic_json>`.
### Always required
- The template must be usable with exactly one type argument. The library instantiates `AllocatorType<T>` directly and
never uses `#!cpp std::allocator_traits<...>::rebind_alloc`.
- It must satisfy the [Allocator](https://en.cppreference.com/w/cpp/named_req/Allocator) named requirement so that
`#!cpp std::allocator_traits` can be used with it.
- It must be **default-constructible and stateless**. Objects are allocated with a default-constructed allocator and
deallocated with a *different* default-constructed allocator, and
[`get_allocator()`](../../api/basic_json/get_allocator.md) returns a default-constructed instance. Allocators
carrying state are not supported, so there is no way to tell a `basic_json` where to allocate from; see the note
under [`StringType`](#stringtype) for what that means in practice. A stateful allocator is **not diagnosed**: it
compiles and silently ignores the state.
- It must support **incomplete types**: `AllocatorType<basic_json>` is instantiated inside the definition of
`basic_json` itself.
- `#!cpp std::allocator_traits<AllocatorType<basic_json>>::pointer` becomes
[`basic_json::pointer`](../../api/basic_json/index.md#container-types), and iterators are constructed from raw
`#!cpp basic_json*` values. The `pointer` type must therefore be a plain pointer; fancy pointers are not supported.
### Compatible types
| Type | Support |
|-------------------------------------------------------------------|----------------------------------------|
| `#!cpp std::allocator` (default) | full |
| a custom stateless allocator template | full |
| stateful allocators, e.g. `#!cpp std::pmr::polymorphic_allocator` | not usable; see the requirements above |
## `JSONSerializer`
`JSONSerializer` is instantiated as `JSONSerializer<T, void>` and defaults to
[`adl_serializer`](../../api/adl_serializer/index.md).
### Always required
- The template must accept **two** type arguments. It does not have to give the second one a default -- `basic_json`
declares the parameter as `#!cpp template<typename T, typename SFINAE = void> class JSONSerializer`, so uses such as
`#!cpp JSONSerializer<T>` inside the library supply `#!cpp void` themselves. The second parameter exists so that
partial specializations can be constrained by SFINAE.
- For every type `T` that is converted **to** a JSON value, a static member function
`#!cpp static void to_json(basic_json&, T)` must exist.
- For every type `T` that is converted **from** a JSON value, either
`#!cpp static void from_json(const basic_json&, T&)` or `#!cpp static T from_json(const basic_json&)` must exist.
The latter form is required for types that are not default-constructible; see
[Arbitrary Types Conversions](../arbitrary_types.md).
- To support the [converting constructor](../../api/basic_json/basic_json.md) between different `basic_json`
specializations, `to_json` must be available for `boolean_t`, `number_integer_t`, `number_unsigned_t`,
`number_float_t`, `string_t`, `object_t`, `array_t`, and `binary_t` of the *source* specialization.
### Compatible types
| Type | Support |
|---------------------------------------------------------------------------|-------------------------------------------------------------------|
| [`nlohmann::adl_serializer`](../../api/adl_serializer/index.md) (default) | full |
| a class template deriving from `adl_serializer` | full; the usual way to change behavior while keeping the defaults |
| an unrelated template with the same interface | full, but it has to handle every type the library converts |
## `BinaryType`
`BinaryType` is not a JSON type; it is used for the byte strings of the
[binary formats](../binary_formats/index.md). It is wrapped as
```cpp
using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
```
### Always required
- A non-`final` class type -- [`byte_container_with_subtype`](../../api/byte_container_with_subtype/index.md) derives
from it publicly.
- A member type `value_type` that is **exactly one byte** wide (e.g., `#!cpp std::uint8_t`, `#!cpp char`, or
`#!cpp std::byte`). Readers and writers reinterpret the container's storage as raw bytes, so a wider `value_type` is
rejected with a `#!cpp static_assert`.
- Contiguous storage: the binary readers `#!cpp std::memcpy` into `#!cpp &binary[n]`, the writers `reinterpret_cast`
`data()`. `#!cpp data() + n` would do for the readers too, but they share one helper with
[`StringType`](#stringtype), whose non-`#!cpp const` `data()` is C++17 and later only.
- Default-constructible, copy-constructible, and move-constructible.
- Member functions `size()`, `empty()`, `data()`, `resize()`, `operator[]`, `back()`, `begin()`, `end()`, `cbegin()`,
and `cend()` with random-access iterators, and `insert(pos, first, last)`, which the CBOR reader uses to join the
chunks of an indefinite-length byte string. `push_back()` is **not** required.
- Comparison operators: `==` is used by
[`byte_container_with_subtype`](../../api/byte_container_with_subtype/index.md), the relational operators by
[`basic_json`'s comparison operators](../../api/basic_json/operator_le.md).
### Required for individual functions
- `clear()`, for [`basic_json::clear()`](../../api/basic_json/clear.md).
`max_size()`, `at()`, `reserve()`, `erase()`, `pop_back()`, and `emplace_back()` are **not** used at all.
See [`binary_t`](../../api/basic_json/binary_t.md) for how a non-default `BinaryType` changes the meaning of assigning
such a container to a `basic_json` value.
!!! tip "Reference implementation"
`docs/mkdocs/docs/examples/custom_binary_type.hpp` wraps a private `#!cpp std::vector<std::uint8_t>` and satisfies
every requirement above -- a good starting point for a custom `BinaryType`.
```cpp
--8<-- "examples/custom_binary_type.hpp"
```
??? example "Compiling and using it"
```cpp
--8<-- "examples/custom_binary_type.cpp"
```
Output:
```json
--8<-- "examples/custom_binary_type.output"
```
### Compatible containers
| Container | Notes |
|---------------------------------------------------------------------------------------------|---------------------------------------------------------------------------|
| `#!cpp std::vector<std::uint8_t>` (default) | |
| `#!cpp std::vector<char>`, `#!cpp std::vector<std::byte>` | `dump()` writes the bytes as 0..255 whichever is used |
| `boost::container::vector<std::uint8_t>`, `boost::container::small_vector<std::uint8_t, N>` | |
| `absl::InlinedVector<std::uint8_t, N>` | usable here, unlike as an `ArrayType`, because the value type is complete |
| `eastl::vector<std::uint8_t>` | usable here, unlike as an `ArrayType`, because `max_size()` is not needed |
| `folly::fbvector<std::uint8_t>` | requires C++20, see the note above |
### Containers that cannot be used
| Container | Reason |
|------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `QByteArray` | no `empty()` (it spells that `isEmpty()`); its `insert` takes an index rather than an iterator; and it converts to `string_t`, which makes `to_json` ambiguous between a string and a binary value |
| `#!cpp std::string` | `binary_t::container_type` and `string_t` would be the same type, so the two [`swap`](../../api/basic_json/swap.md) overloads collide and `basic_json` cannot be instantiated at all |
| `#!cpp std::deque<std::uint8_t>` | storage is not contiguous, so there is no `data()` |
| containers whose `value_type` is wider than one byte | see above -- accepted by the compiler, wrong at runtime |
## `CustomBaseClass`
`CustomBaseClass` is an extension point: unless it is `#!cpp void` (the default, which selects the empty
`nlohmann::json_default_base`), `basic_json` publicly derives from it.
### Always required
- A non-`final`, default-constructible class type.
- `basic_json` is copy-/move-constructible and copy-/move-assignable only if `CustomBaseClass` is.
### Notes
`basic_json` is documented to be a
[StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType). Because `basic_json` has
non-static data members of its own, a `CustomBaseClass` with non-static data members forfeits this guarantee.
Note the namespace of `CustomBaseClass` becomes an associated namespace of `basic_json` for the purpose of
argument-dependent lookup.
See [`json_base_class_t`](../../api/basic_json/json_base_class_t.md) for an example.
### Compatible types
| Type | Support |
|----------------------------------------------|----------------------------------------------------------------------------|
| `#!cpp void` (default) | an empty base class is used; no effect on `basic_json` |
| any default-constructible, non-`final` class | full; see [`json_base_class_t`](../../api/basic_json/json_base_class_t.md) |
## Cross-specialization conversions
Converting a value from one `basic_json` specialization into another (see the
[converting constructor](../../api/basic_json/basic_json.md)) imposes two additional requirements that are not
diagnosed at compile time. With assertions enabled they abort on the `#!cpp JSON_ASSERT` at the end of the converting
constructor; under `#!cpp NDEBUG` they fail **silently** at runtime:
- The target `string_t` must be directly constructible from the source `string_t`. Otherwise the string is converted to
an array of character codes.
- The target `object_t::key_type` must be directly constructible from the source object's key type. Otherwise the
object is converted to an array of key/value pairs.
See [issue #3425](https://github.com/nlohmann/json/issues/3425), [`string_t`](../../api/basic_json/string_t.md), and
[`object_t`](../../api/basic_json/object_t.md).
## See also
- [Types](index.md) -- overview of how JSON values are stored
- [Number Handling](number_handling.md) -- how the number types affect parsing and serialization
- [Object Order](../object_order.md) -- using an insertion-ordered `ObjectType`
- [`basic_json`](../../api/basic_json/index.md) -- API documentation of the class template
@@ -0,0 +1,679 @@
<!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/types/template_parameters/" rel="canonical"><link href=../number_handling/ rel=prev><link href=../../../integration/ rel=next><link rel=icon href=../../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>Template Parameter Requirements - 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=#template-parameter-requirements 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> Template Parameter Requirements </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.5Line truncated
<span class=w> </span><span class=n>basic_json</span><span class=p>,</span><span class=w> </span><span class=c1>// mapped_type</span>
<span class=w> </span><span class=n>default_object_comparator_t</span><span class=p>,</span><span class=w> </span><span class=c1>// key_compare</span>
<span class=w> </span><span class=n>AllocatorType</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>StringType</span><span class=p>,</span>
<span class=w> </span><span class=n>basic_json</span><span class=o>&gt;&gt;&gt;</span><span class=p>;</span><span class=w> </span><span class=c1>// allocator_type</span>
</code></pre></div> <p>i.e., the template arguments follow the order and meaning of <code>std::map</code>.</p> <h3 id=always-required>Always required<a class=headerlink href=#always-required title="Permanent link">&para;</a></h3> <ul> <li>The template must be usable with <strong>four</strong> type arguments in the order shown above. The third argument is a <strong>comparator</strong>; containers that expect something else in this position (e.g., a hash function) need an alias template or wrapper -- see <a href=#notes>Notes</a>.</li> <li>An optional member type <code>key_compare</code>. If it is present it becomes <a href=../../../api/basic_json/object_comparator_t/ ><code>object_comparator_t</code></a>; otherwise <a href=../../../api/basic_json/default_object_comparator_t/ ><code>default_object_comparator_t</code></a> is used.</li> <li>Member types <code>key_type</code>, <code>mapped_type</code>, <code>value_type</code>, and <code>iterator</code>.</li> <li><code>value_type</code> must behave like <code class=highlight><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_type</span><span class=p>,</span><span class=w> </span><span class=n>mapped_type</span><span class=o>&gt;</span></code>; the library accesses <code>.first</code> and <code>.second</code> on it.</li> <li><code>iterator</code> must be default-constructible and satisfy <a href="https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator">LegacyBidirectionalIterator</a>. The type returned by <code>cbegin()</code>/<code>cend()</code> must satisfy the same requirements.</li> <li>Constructors: default, copy, move, and from an iterator range <code>(first, last)</code>.</li> <li>Member functions <code>begin()</code>, <code>end()</code>, <code>cbegin()</code>, <code>cend()</code>, <code>empty()</code>, <code>size()</code>, <code>max_size()</code>, <code>clear()</code>, <code>find(key)</code>, <code>count(key)</code>, <code>emplace(key, value)</code>, <code>insert(value_type)</code>, <code>insert(first, last)</code>, <code>operator[](key)</code>, <code>erase(iterator)</code>, and <code>erase(first, last)</code>. <code>erase(iterator)</code> may return the following iterator or <code class=highlight><span class=kt>void</span></code>; in the latter case the library computes the successor itself, before erasing.</li> <li><code>erase(key)</code> is <strong>optional</strong>: if the container does not provide one, the library falls back to <code>find(key)</code> followed by <code>erase(iterator)</code>.</li> <li><code>at(key)</code> is required only by <a href=../../../api/basic_json/to_ubjson/ ><code>to_ubjson</code></a> and <a href=../../../api/basic_json/to_bjdata/ ><code>to_bjdata</code></a>, but every container tried here provides it.</li> <li><code>emplace</code> and <code>insert(value_type)</code> must return <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>pair</span><span class=o>&lt;</span><span class=n>iterator</span><span class=p>,</span><span class=w> </span><span class=kt>bool</span><span class=o>&gt;</span></code> and must have <strong>unique-key</strong> semantics; multimaps cannot be used.</li> <li>The type must be swappable (via <code>std::swap</code> or an <abbr title="Argument-dependent lookup">ADL</abbr> <code>swap</code>).</li> <li>The comparison operators <code>==</code> and <code>&lt;</code>; <code>!=</code>, <code>&lt;=</code>, <code>&gt;</code>, and <code>&gt;=</code> are derived from them. Where the library uses three-way comparison (C++20), <code>==</code> and <code>&lt;=&gt;</code> are required <strong>instead</strong> -- the six two-way operators do not satisfy it. They implement <a href=../../../api/basic_json/operator_eq/ ><code>basic_json</code>'s comparison operators</a>.</li> </ul> <h3 id=required-for-heterogeneous-key-lookup>Required for heterogeneous key lookup<a class=headerlink href=#required-for-heterogeneous-key-lookup title="Permanent link">&para;</a></h3> <p>The overloads of <a href=../../../api/basic_json/at/ ><code>at</code></a>, <a href=../../../api/basic_json/operator%5B%5D/ ><code>operator[]</code></a>, <a href=../../../api/basic_json/find/ ><code>find</code></a>, <a href=../../../api/basic_json/contains/ ><code>contains</code></a>, <a href=../../../api/basic_json/count/ ><code>count</code></a>, <a href=../../../api/basic_json/erase/ ><code>erase</code></a>, and <a href=../../../api/basic_json/value/ ><code>value</code></a> that accept a key type other than <code>object_t::key_type</code> require</p> <ul> <li>a <strong>transparent</strong> comparator, i.e. <a href=../../../api/basic_json/object_comparator_t/ ><code>object_comparator_t</code></a> has a member type <code>is_transparent</code> (this is why the default comparator is <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>less</span><span class=o>&lt;&gt;</span></code> sincLine truncated
<span class=k>struct</span><span class=w> </span><span class=nc>unordered_map_object</span>
<span class=w> </span><span class=o>:</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>unordered_map</span><span class=o>&lt;</span><span class=n>Key</span><span class=p>,</span><span class=w> </span><span class=n>T</span><span class=p>,</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>hash</span><span class=o>&lt;</span><span class=n>Key</span><span class=o>&gt;</span><span class=p>,</span><span class=w> </span><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=p>,</span><span class=w> </span><span class=n>Allocator</span><span class=o>&gt;</span>
<span class=p>{</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>base_t</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>unordered_map</span><span class=o>&lt;</span><span class=n>Key</span><span class=p>,</span><span class=w> </span><span class=n>T</span><span class=p>,</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>hash</span><span class=o>&lt;</span><span class=n>Key</span><span class=o>&gt;</span><span class=p>,</span><span class=w> </span><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=p>,</span><span class=w> </span><span class=n>Allocator</span><span class=o>&gt;</span><span class=p>;</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>base_t</span><span class=o>::</span><span class=n>base_t</span><span class=p>;</span>
<span class=p>};</span>
<span class=k>using</span><span class=w> </span><span class=n>unordered_json</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>nlohmann</span><span class=o>::</span><span class=n>basic_json</span><span class=o>&lt;</span><span class=n>unordered_map_object</span><span class=o>&gt;</span><span class=p>;</span>
</code></pre></div> <p>Whether <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>unordered_map</span></code> can be instantiated at all depends on the standard library: <code>object_t</code> is formed while <code>basic_json</code> is still incomplete (see the warning above), and libstdc++ 9 needs the size of the mapped type to instantiate the hash map's node type, so the adapter does not compile there. Newer libstdc++ versions, and the hash maps listed below, do not have that problem.</p> <p>The adapter above works verbatim for Abseil's, Boost's, <code>phmap</code>'s and <code>gtl</code>'s hash maps, which all place the hash function third and take a <code class=highlight><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></code> allocator fifth. Two need a different adapter:</p> <ul> <li><code>ankerl::unordered_dense</code> expects an allocator over <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>pair</span><span class=o>&lt;</span><span class=n>Key</span><span class=p>,</span><span class=w> </span><span class=n>T</span><span class=o>&gt;</span></code> (non-const key), so the allocator has to be rebound to that or dropped.</li> <li><code>robin_hood</code>'s fifth parameter is the non-type <code>MaxLoadFactor100</code>, so its adapter must drop the allocator entirely.</li> </ul> <p>None of these hash maps defines <code>key_compare</code>, so all of them additionally rely on <code>object_comparator_t</code> falling back to <a href=../../../api/basic_json/default_object_comparator_t/ ><code>default_object_comparator_t</code></a>; see <a href=../../../api/basic_json/object_comparator_t/ ><code>object_comparator_t</code></a>.</p> <h4 id=abseil-hash-maps>Abseil hash maps<a class=headerlink href=#abseil-hash-maps title="Permanent link">&para;</a></h4> <p><code>absl::flat_hash_map</code> and <code>absl::node_hash_map</code> tolerate an incomplete value type, but they take a hash function as their third template argument. The same adapter as for <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>unordered_map</span></code> makes them usable:</p> <div class=highlight><pre><span></span><code><span class=k>template</span><span class=o>&lt;</span><span class=k>class</span><span class=w> </span><span class=nc>Key</span><span class=p>,</span><span class=w> </span><span class=k>class</span><span class=w> </span><span class=nc>T</span><span class=p>,</span><span class=w> </span><span class=k>class</span><span class=w> </span><span class=nc>IgnoredCompare</span><span class=p>,</span><span class=w> </span><span class=k>class</span><span class=w> </span><span class=nc>Allocator</span><span class=o>&gt;</span>
<span class=k>struct</span><span class=w> </span><span class=nc>flat_hash_object</span>
<span class=w> </span><span class=o>:</span><span class=w> </span><span class=n>absl</span><span class=o>::</span><span class=n>flat_hash_map</span><span class=o>&lt;</span><span class=n>Key</span><span class=p>,</span><span class=w> </span><span class=n>T</span><span class=p>,</span><span class=w> </span><span class=n>absl</span><span class=o>::</span><span class=n>Hash</span><span class=o>&lt;</span><span class=n>Key</span><span class=o>&gt;</span><span class=p>,</span><span class=w> </span><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=p>,</span><span class=w> </span><span class=n>Allocator</span><span class=o>&gt;</span>
<span class=p>{</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>base_t</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>absl</span><span class=o>::</span><span class=n>flat_hash_map</span><span class=o>&lt;</span><span class=n>Key</span><span class=p>,</span><span class=w> </span><span class=n>T</span><span class=p>,</span><span class=w> </span><span class=n>absl</span><span class=o>::</span><span class=n>Hash</span><span class=o>&lt;</span><span class=n>Key</span><span class=o>&gt;</span><span class=p>,</span><span class=w> </span><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=p>,</span><span class=w> </span><span class=n>Allocator</span><span class=o>&gt;</span><span class=p>;</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>base_t</span><span class=o>::</span><span class=n>base_t</span><span class=p>;</span>
<span class=p>};</span>
<span class=k>using</span><span class=w> </span><span class=n>flat_hash_json</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>nlohmann</span><span class=o>::</span><span class=n>basic_json</span><span class=o>&lt;</span><span class=n>flat_hash_object</span><span class=o>&gt;</span><span class=p>;</span>
</code></pre></div> <p><code>absl::node_hash_map</code> keeps references to the mapped values valid across insertions; <code>absl::flat_hash_map</code> does not, which makes it behave like <a href=../../../api/ordered_json/ ><code>ordered_json</code></a> with respect to <a href=../../../api/basic_json/#iterator-invalidation>iterator invalidation</a>. Both expose a <code>capacity()</code> member function, so <a href=../../../api/macros/json_diagnostics/ ><code>JSON_DIAGNOSTICS</code></a> treats them conservatively and keeps the parent pointers correct either way.</p> <h4 id=iteration-order>Iteration order<a class=headerlink href=#iteration-order title="Permanent link">&para;</a></h4> <p>The library never relies on the container's iteration order for correctness; it does determine the order in which object keys are serialized by <a href=../../../api/basic_json/dump/ ><code>dump</code></a> and visited by <a href=../../../api/basic_json/items/ ><code>items</code></a>. See <a href=../../object_order/ >Object Order</a>.</p> <h4 id=capacity-marks-a-container-as-insertion-ordered><code>capacity()</code> marks a container as insertion-ordered<a class=headerlink href=#capacity-marks-a-container-as-insertion-ordered title="Permanent link">&para;</a></h4> <p>With <a href=../../../api/macros/json_diagnostics/ ><code>JSON_DIAGNOSTICS</code></a> enabled, the library detects insertion-ordered maps by probing for a <code>capacity()</code> member function (<code>nlohmann::ordered_map</code> inherits it from <code>std::vector</code>) and refreshes all parent pointers after every insertion. An <code>ObjectType</code> that happens to have a <code>capacity()</code> member is therefore treated conservatively -- this is correct, but slower.</p> <h4 id=key-order-and-duplicate-keys>Key order and duplicate keys<a class=headerlink href=#key-order-and-duplicate-keys title="Permanent link">&para;</a></h4> <p>The library does not sort or de-duplicate keys itself; the behavior described in <a href=../../../api/basic_json/object_t/ ><code>object_t</code></a> is entirely the behavior of the chosen container.</p> <div class="admonition tip"> <p class=admonition-title>Reference implementation</p> <p><code>docs/mkdocs/docs/examples/custom_object_type.hpp</code> wraps a private <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>map</span></code> and satisfies every requirement above. It does not define <code>key_compare</code>, so <code>object_comparator_t</code> falls back to <a href=../../../api/basic_json/default_object_comparator_t/ ><code>default_object_comparator_t</code></a> -- a good starting point for a custom <code>ObjectType</code>.</p> <div class=highlight><pre><span></span><code><span class=cp>#pragma once</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;map&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;utility&gt;</span>
<span class=c1>// A minimal, self-contained ObjectType built around a private std::map.</span>
<span class=c1>// key_compare is deliberately not exposed: when an ObjectType has no</span>
<span class=c1>// key_compare member, the library falls back to its own default comparator.</span>
<span class=c1>// See https://json.nlohmann.me/features/types/template_parameters/#objecttype</span>
<span class=k>template</span><span class=o>&lt;</span><span class=k>class</span><span class=w> </span><span class=nc>Key</span><span class=p>,</span><span class=w> </span><span class=k>class</span><span class=w> </span><span class=nc>T</span><span class=p>,</span><span class=w> </span><span class=k>class</span><span class=w> </span><span class=nc>Compare</span><span class=p>,</span><span class=w> </span><span class=k>class</span><span class=w> </span><span class=nc>Allocator</span><span class=o>&gt;</span>
<span class=k>class</span><span class=w> </span><span class=nc>custom_object_type</span>
<span class=p>{</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>map_t</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>map</span><span class=o>&lt;</span><span class=n>Key</span><span class=p>,</span><span class=w> </span><span class=n>T</span><span class=p>,</span><span class=w> </span><span class=n>Compare</span><span class=p>,</span><span class=w> </span><span class=n>Allocator</span><span class=o>&gt;</span><span class=p>;</span>
<span class=w> </span><span class=n>map_t</span><span class=w> </span><span class=n>data_</span><span class=p>;</span>
<span class=w> </span><span class=k>public</span><span class=o>:</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>key_type</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>typename</span><span class=w> </span><span class=nc>map_t</span><span class=o>::</span><span class=n>key_type</span><span class=p>;</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>mapped_type</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>typename</span><span class=w> </span><span class=nc>map_t</span><span class=o>::</span><span class=n>mapped_type</span><span class=p>;</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>value_type</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>typename</span><span class=w> </span><span class=nc>map_t</span><span class=o>::</span><span class=n>value_type</span><span class=p>;</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>size_type</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>typename</span><span class=w> </span><span class=nc>map_t</span><span class=o>::</span><span class=n>size_type</span><span class=p>;</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>typename</span><span class=w> </span><span class=nc>map_t</span><span class=o>::</span><span class=n>iterator</span><span class=p>;</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>typename</span><span class=w> </span><span class=nc>map_t</span><span class=o>::</span><span class=n>const_iterator</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_object_type</span><span class=p>()</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_object_type</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>custom_object_type</span><span class=o>&amp;</span><span class=p>)</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_object_type</span><span class=p>(</span><span class=n>custom_object_type</span><span class=o>&amp;&amp;</span><span class=p>)</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_object_type</span><span class=o>&amp;</span><span class=w> </span><span class=k>operator</span><span class=o>=</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>custom_object_type</span><span class=o>&amp;</span><span class=p>)</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_object_type</span><span class=o>&amp;</span><span class=w> </span><span class=k>operator</span><span class=o>=</span><span class=p>(</span><span class=n>custom_object_type</span><span class=o>&amp;&amp;</span><span class=p>)</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=k>template</span><span class=o>&lt;</span><span class=k>class</span><span class=w> </span><span class=nc>InputIt</span><span class=o>&gt;</span>
<span class=w> </span><span class=n>custom_object_type</span><span class=p>(</span><span class=n>InputIt</span><span class=w> </span><span class=n>first</span><span class=p>,</span><span class=w> </span><span class=n>InputIt</span><span class=w> </span><span class=n>last</span><span class=p>)</span><span class=w> </span><span class=o>:</span><span class=w> </span><span class=n>data_</span><span class=p>(</span><span class=n>first</span><span class=p>,</span><span class=w> </span><span class=n>last</span><span class=p>)</span><span class=w> </span><span class=p>{}</span>
<span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=n>begin</span><span class=p>()</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>begin</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=n>end</span><span class=p>()</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>end</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=n>begin</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>begin</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=n>end</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>end</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=n>cbegin</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>cbegin</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=n>cend</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>cend</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=n>empty</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>empty</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>size_type</span><span class=w> </span><span class=n>size</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>size</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>size_type</span><span class=w> </span><span class=n>max_size</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>max_size</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>void</span><span class=w> </span><span class=n>clear</span><span class=p>()</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>clear</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=n>find</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>key_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>key</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>find</span><span class=p>(</span><span class=n>key</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=n>find</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>key_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>key</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>find</span><span class=p>(</span><span class=n>key</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>size_type</span><span class=w> </span><span class=n>count</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>key_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>key</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>count</span><span class=p>(</span><span class=n>key</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>pair</span><span class=o>&lt;</span><span class=n>iterator</span><span class=p>,</span><span class=w> </span><span class=kt>bool</span><span class=o>&gt;</span><span class=w> </span><span class=n>emplace</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>key_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>key</span><span class=p>,</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>mapped_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>value</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>emplace</span><span class=p>(</span><span class=n>key</span><span class=p>,</span><span class=w> </span><span class=n>value</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>pair</span><span class=o>&lt;</span><span class=n>iterator</span><span class=p>,</span><span class=w> </span><span class=kt>bool</span><span class=o>&gt;</span><span class=w> </span><span class=n>insert</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>value_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>value</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>insert</span><span class=p>(</span><span class=n>value</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=k>template</span><span class=o>&lt;</span><span class=k>class</span><span class=w> </span><span class=nc>InputIt</span><span class=o>&gt;</span>
<span class=w> </span><span class=kt>void</span><span class=w> </span><span class=n>insert</span><span class=p>(</span><span class=n>InputIt</span><span class=w> </span><span class=n>first</span><span class=p>,</span><span class=w> </span><span class=n>InputIt</span><span class=w> </span><span class=n>last</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>insert</span><span class=p>(</span><span class=n>first</span><span class=p>,</span><span class=w> </span><span class=n>last</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>mapped_type</span><span class=o>&amp;</span><span class=w> </span><span class=k>operator</span><span class=p>[](</span><span class=k>const</span><span class=w> </span><span class=n>key_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>key</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>[</span><span class=n>key</span><span class=p>];</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>mapped_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>at</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>key_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>key</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>at</span><span class=p>(</span><span class=n>key</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>mapped_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>at</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>key_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>key</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>at</span><span class=p>(</span><span class=n>key</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=n>erase</span><span class=p>(</span><span class=n>iterator</span><span class=w> </span><span class=n>pos</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>erase</span><span class=p>(</span><span class=n>pos</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=n>erase</span><span class=p>(</span><span class=n>iterator</span><span class=w> </span><span class=n>first</span><span class=p>,</span><span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=n>last</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>erase</span><span class=p>(</span><span class=n>first</span><span class=p>,</span><span class=w> </span><span class=n>last</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>size_type</span><span class=w> </span><span class=n>erase</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>key_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>key</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>erase</span><span class=p>(</span><span class=n>key</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>void</span><span class=w> </span><span class=n>swap</span><span class=p>(</span><span class=n>custom_object_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>other</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>swap</span><span class=p>(</span><span class=n>other</span><span class=p>.</span><span class=n>data_</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=k>friend</span><span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=k>operator</span><span class=o>==</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>custom_object_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>lhs</span><span class=p>,</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>custom_object_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>rhs</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>lhs</span><span class=p>.</span><span class=n>data_</span><span class=w> </span><span class=o>==</span><span class=w> </span><span class=n>rhs</span><span class=p>.</span><span class=n>data_</span><span class=p>;</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=k>friend</span><span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=k>operator</span><span class=o>&lt;</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>custom_object_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>lhs</span><span class=p>,</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>custom_object_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>rhs</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>lhs</span><span class=p>.</span><span class=n>data_</span><span class=w> </span><span class=o>&lt;</span><span class=w> </span><span class=n>rhs</span><span class=p>.</span><span class=n>data_</span><span class=p>;</span>
<span class=w> </span><span class=p>}</span>
<span class=p>};</span>
</code></pre></div> </div> <details class=example> <summary>Compiling and using it</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;type_traits&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;vector&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;nlohmann/json.hpp&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>"custom_object_type.hpp"</span>
<span class=k>using</span><span class=w> </span><span class=n>custom_json</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>nlohmann</span><span class=o>::</span><span class=n>basic_json</span><span class=o>&lt;</span><span class=n>custom_object_type</span><span class=p>,</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>vector</span><span class=o>&gt;</span><span class=p>;</span>
<span class=kt>int</span><span class=w> </span><span class=nf>main</span><span class=p>()</span>
<span class=p>{</span>
<span class=w> </span><span class=n>custom_json</span><span class=w> </span><span class=n>j</span><span class=p>;</span>
<span class=w> </span><span class=n>j</span><span class=p>[</span><span class=s>"pi"</span><span class=p>]</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=mf>3.141</span><span class=p>;</span>
<span class=w> </span><span class=n>j</span><span class=p>[</span><span class=s>"happy"</span><span class=p>]</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=n>j</span><span class=p>[</span><span class=s>"list"</span><span class=p>]</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=p>{</span><span class=mi>1</span><span class=p>,</span><span class=w> </span><span class=mi>2</span><span class=p>,</span><span class=w> </span><span class=mi>3</span><span class=p>};</span>
<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=n>j</span><span class=p>.</span><span class=n>dump</span><span class=p>(</span><span class=mi>2</span><span class=p>)</span><span class=w> </span><span class=o>&lt;&lt;</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>endl</span><span class=p>;</span>
<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=n>std</span><span class=o>::</span><span class=n>boolalpha</span><span class=w> </span><span class=o>&lt;&lt;</span><span class=w> </span><span class=p>(</span><span class=n>custom_json</span><span class=o>::</span><span class=n>parse</span><span class=p>(</span><span class=n>j</span><span class=p>.</span><span class=n>dump</span><span class=p>())</span><span class=w> </span><span class=o>==</span><span class=w> </span><span class=n>j</span><span class=p>)</span><span class=w> </span><span class=o>&lt;&lt;</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>endl</span><span class=p>;</span>
<span class=w> </span><span class=c1>// custom_object_type has no key_compare member, so object_comparator_t</span>
<span class=w> </span><span class=c1>// falls back to its default</span>
<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=n>std</span><span class=o>::</span><span class=n>boolalpha</span>
<span class=w> </span><span class=o>&lt;&lt;</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>is_same</span><span class=o>&lt;</span><span class=n>custom_json</span><span class=o>::</span><span class=n>object_comparator_t</span><span class=p>,</span><span class=w> </span><span class=n>custom_json</span><span class=o>::</span><span class=n>default_object_comparator_t</span><span class=o>&gt;::</span><span class=n>value</span>
<span class=w> </span><span class=o>&lt;&lt;</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>endl</span><span class=p>;</span>
<span class=p>}</span>
</code></pre></div> <p>Output:</p> <div class=highlight><pre><span></span><code><span class=p>{</span>
<span class=w> </span><span class=nt>"happy"</span><span class=p>:</span><span class=w> </span><span class=kc>true</span><span class=p>,</span>
<span class=w> </span><span class=nt>"list"</span><span class=p>:</span><span class=w> </span><span class=p>[</span>
<span class=w> </span><span class=mi>1</span><span class=p>,</span>
<span class=w> </span><span class=mi>2</span><span class=p>,</span>
<span class=w> </span><span class=mi>3</span>
<span class=w> </span><span class=p>],</span>
<span class=w> </span><span class=nt>"pi"</span><span class=p>:</span><span class=w> </span><span class=mf>3.141</span>
<span class=p>}</span>
<span class=kc>true</span>
<span class=kc>true</span>
</code></pre></div> </details> <h3 id=compatible-containers>Compatible containers<a class=headerlink href=#compatible-containers title="Permanent link">&para;</a></h3> <table> <thead> <tr> <th>Container</th> <th>Notes</th> </tr> </thead> <tbody> <tr> <td><code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>map</span></code> (default)</td> <td></td> </tr> <tr> <td><a href=../../../api/ordered_map/ ><code>nlohmann::ordered_map</code></a></td> <td>used by <a href=../../../api/ordered_json/ ><code>ordered_json</code></a>; keeps insertion order</td> </tr> <tr> <td><a href="https://github.com/nlohmann/fifo_map"><code>nlohmann::fifo_map</code></a></td> <td>keeps insertion order; adapter puts <code>fifo_map_compare</code> in the comparator slot</td> </tr> <tr> <td><code>boost::container::map</code>, <code>boost::container::flat_map</code></td> <td>no adapter needed</td> </tr> <tr> <td><code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>unordered_map</span></code></td> <td>through the adapter above; not with libstdc++ 9, see the note</td> </tr> <tr> <td><code>boost::unordered_map</code>, <code>boost::unordered_flat_map</code>, <code>boost::unordered_node_map</code></td> <td>through the adapter above</td> </tr> <tr> <td><code>absl::flat_hash_map</code>, <code>absl::node_hash_map</code></td> <td>through the adapter above; <code>flat_hash_map</code> moves mapped values on rehash</td> </tr> <tr> <td><code>phmap::flat_hash_map</code>, <code>phmap::node_hash_map</code>, <code>gtl::flat_hash_map</code></td> <td>through the adapter above</td> </tr> <tr> <td><code>ankerl::unordered_dense::map</code> and <code>segmented_map</code></td> <td>adapter must rebind or drop the allocator</td> </tr> <tr> <td><code>robin_hood::unordered_flat_map</code></td> <td>adapter must drop the allocator</td> </tr> <tr> <td><code>folly::F14NodeMap</code></td> <td>through the adapter above; requires C++20, see the note above</td> </tr> <tr> <td><code>folly::sorted_vector_map</code></td> <td>alias must drop the allocator, whose value type it disagrees on</td> </tr> </tbody> </table> <h3 id=containers-that-cannot-be-used>Containers that cannot be used<a class=headerlink href=#containers-that-cannot-be-used title="Permanent link">&para;</a></h3> <table> <thead> <tr> <th>Container</th> <th>Reason</th> </tr> </thead> <tbody> <tr> <td><code>absl::btree_map</code>, <code>phmap::btree_map</code>, <code>gtl::btree_map</code></td> <td>require a complete mapped type</td> </tr> <tr> <td><code>robin_hood::unordered_node_map</code>, <code>folly::F14FastMap</code>, <code>eastl::hash_map</code></td> <td>require a complete mapped type</td> </tr> <tr> <td><code>eastl::map</code></td> <td>EASTL iterators do not work with <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>iterator_traits</span></code></td> </tr> <tr> <td><code>tsl::ordered_map</code></td> <td>its iterators expose the mapped value as <code class=highlight><span class=k>const</span></code></td> </tr> <tr> <td><code>QMap</code></td> <td>no <code>value_type</code> member type</td> </tr> <tr> <td><code>QHash</code></td> <td>its <code>value_type</code> is the mapped type rather than a key/value pair, and its iterators dereference to the mapped value</td> </tr> <tr> <td><code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>multimap</span></code>, <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>unordered_multimap</span></code></td> <td><code>emplace</code> does not return <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>pair</span><span class=o>&lt;</span><span class=n>iterator</span><span class=p>,</span><span class=w> </span><span class=kt>bool</span><span class=o>&gt;</span></code></td> </tr> </tbody> </table> <h2 id=arraytype><code>ArrayType</code><a class=headerlink href=#arraytype title="Permanent link">&para;</a></h2> <p><code>ArrayType</code> is instantiated as</p> <div class=highlight><pre><span></span><code><span class=k>using</span><span class=w> </span><span class=n>array_t</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>ArrayType</span><span class=o>&lt;</span><span class=n>basic_json</span><span class=p>,</span><span class=w> </span><span class=n>AllocatorType</span><span class=o>&lt;</span><span class=n>basic_json</span><span class=o>&gt;&gt;</span><span class=p>;</span>
</code></pre></div> <h3 id=always-required_1>Always required<a class=headerlink href=#always-required_1 title="Permanent link">&para;</a></h3> <ul> <li>The template must be usable with <strong>two</strong> type arguments (value type and allocator).</li> <li>Member types <code>value_type</code> and <code>iterator</code>.</li> <li>Constructors: default, copy, and move; and from an iterator range <code>(first, last)</code>.</li> <li>Member functions <code>begin()</code>, <code>end()</code>, <code>cbegin()</code>, <code>cend()</code>, <code>empty()</code>, <code>size()</code>, <code>max_size()</code>, <code>clear()</code>, <code>operator[](size_type)</code>, <code>back()</code>, <code>push_back()</code>, <code>emplace_back()</code>, <code>pop_back()</code>, <code>resize()</code>, <code>insert()</code> (single element, count, and range), <code>erase(pos)</code>, and <code>erase(first, last)</code>. <code>basic_json::insert(pos, initializer_list)</code> goes through the range overload, so no initializer-list <code>insert</code> is needed. <code>at(size_type)</code> is <strong>not</strong> required: <a href=../../../api/basic_json/at/ ><code>basic_json::at(size_type)</code></a> checks the index itself and then uses <code>operator[]</code>.</li> <li><code>iterator</code> must be default-constructible, and it as well as the type returned by <code>cbegin()</code>/<code>cend()</code> must satisfy <a href="https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator">LegacyRandomAccessIterator</a>. A <code class=highlight><span class=k>static_assert</span></code> only checks for <a href="https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator">LegacyBidirectionalIterator</a>, but <a href=../../../api/basic_json/dump/ ><code>dump</code></a> (<code>cend() - 1</code>), <a href=../../../api/basic_json/erase/ ><code>erase(idx)</code></a> (<code>begin() + idx</code>), and the random-access operations of <a href=../../../api/basic_json/begin/ ><code>basic_json::iterator</code></a> require random access.</li> <li>The comparison operators, as for <a href=#objecttype><code>ObjectType</code></a>: <code>==</code> and <code>&lt;</code>, or <code>==</code> and <code>&lt;=&gt;</code> under C++20.</li> </ul> <h3 id=required-for-individual-functions>Required for individual functions<a class=headerlink href=#required-for-individual-functions title="Permanent link">&para;</a></h3> <ul> <li>A member type <code>value_type</code>, for <a href=../../../api/basic_json/to_bson/ ><code>to_bson</code></a> of an array.</li> <li>A constructor from <code>(count, value)</code>, for <a href=../../../api/basic_json/basic_json/ ><code>basic_json(size_type, const basic_json&amp;)</code></a>.</li> <li>Swappability, via <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>swap</span></code> or an <abbr title="Argument-dependent lookup">ADL</abbr> <code>swap</code>, for <a href=../../../api/basic_json/swap/ ><code>swap(array_t&amp;)</code></a>.</li> </ul> <div class="admonition note"> <p class=admonition-title><code>capacity()</code> is optional</p> <p>With <a href=../../../api/macros/json_diagnostics/ ><code>JSON_DIAGNOSTICS</code></a> enabled, the library reads <code>array_t::capacity()</code> to find out whether adding an element reallocated the array and moved its elements, which would invalidate the parent pointers. An array type without a <code>capacity()</code> member function is handled conservatively: the parent pointers of all elements are refreshed after every insertion, which makes adding <em>n</em> elements cost O(*n*²). Only diagnostics builds pay this; without them <code>capacity()</code> is never called.</p> </div> <div class="admonition tip"> <p class=admonition-title>Reference implementation</p> <p><code>docs/mkdocs/docs/examples/custom_array_type.hpp</code> wraps a private <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>vector</span></code> and satisfies every requirement above -- a good starting point for a custom <code>ArrayType</code>.</p> <div class=highlight><pre><span></span><code><span class=cp>#pragma once</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;memory&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;utility&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;vector&gt;</span>
<span class=c1>// A minimal, self-contained ArrayType built around a private std::vector.</span>
<span class=c1>// See https://json.nlohmann.me/features/types/template_parameters/#arraytype</span>
<span class=k>template</span><span class=o>&lt;</span><span class=k>class</span><span class=w> </span><span class=nc>T</span><span class=p>,</span><span class=w> </span><span class=k>class</span><span class=w> </span><span class=nc>Allocator</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>allocator</span><span class=o>&lt;</span><span class=n>T</span><span class=o>&gt;&gt;</span>
<span class=k>class</span><span class=w> </span><span class=nc>custom_array_type</span>
<span class=p>{</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>vector_t</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>vector</span><span class=o>&lt;</span><span class=n>T</span><span class=p>,</span><span class=w> </span><span class=n>Allocator</span><span class=o>&gt;</span><span class=p>;</span>
<span class=w> </span><span class=n>vector_t</span><span class=w> </span><span class=n>data_</span><span class=p>;</span>
<span class=w> </span><span class=k>public</span><span class=o>:</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>value_type</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>typename</span><span class=w> </span><span class=nc>vector_t</span><span class=o>::</span><span class=n>value_type</span><span class=p>;</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>size_type</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>typename</span><span class=w> </span><span class=nc>vector_t</span><span class=o>::</span><span class=n>size_type</span><span class=p>;</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>typename</span><span class=w> </span><span class=nc>vector_t</span><span class=o>::</span><span class=n>iterator</span><span class=p>;</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>typename</span><span class=w> </span><span class=nc>vector_t</span><span class=o>::</span><span class=n>const_iterator</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_array_type</span><span class=p>()</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_array_type</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>custom_array_type</span><span class=o>&amp;</span><span class=p>)</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_array_type</span><span class=p>(</span><span class=n>custom_array_type</span><span class=o>&amp;&amp;</span><span class=p>)</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_array_type</span><span class=o>&amp;</span><span class=w> </span><span class=k>operator</span><span class=o>=</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>custom_array_type</span><span class=o>&amp;</span><span class=p>)</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_array_type</span><span class=o>&amp;</span><span class=w> </span><span class=k>operator</span><span class=o>=</span><span class=p>(</span><span class=n>custom_array_type</span><span class=o>&amp;&amp;</span><span class=p>)</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=k>template</span><span class=o>&lt;</span><span class=k>class</span><span class=w> </span><span class=nc>InputIt</span><span class=o>&gt;</span>
<span class=w> </span><span class=n>custom_array_type</span><span class=p>(</span><span class=n>InputIt</span><span class=w> </span><span class=n>first</span><span class=p>,</span><span class=w> </span><span class=n>InputIt</span><span class=w> </span><span class=n>last</span><span class=p>)</span><span class=w> </span><span class=o>:</span><span class=w> </span><span class=n>data_</span><span class=p>(</span><span class=n>first</span><span class=p>,</span><span class=w> </span><span class=n>last</span><span class=p>)</span><span class=w> </span><span class=p>{}</span>
<span class=w> </span><span class=n>custom_array_type</span><span class=p>(</span><span class=n>size_type</span><span class=w> </span><span class=n>count</span><span class=p>,</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>T</span><span class=o>&amp;</span><span class=w> </span><span class=n>value</span><span class=p>)</span><span class=w> </span><span class=o>:</span><span class=w> </span><span class=n>data_</span><span class=p>(</span><span class=n>count</span><span class=p>,</span><span class=w> </span><span class=n>value</span><span class=p>)</span><span class=w> </span><span class=p>{}</span>
<span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=n>begin</span><span class=p>()</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>begin</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=n>end</span><span class=p>()</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>end</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=n>begin</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>begin</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=n>end</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>end</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=n>cbegin</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>cbegin</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=n>cend</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>cend</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=n>empty</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>empty</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>size_type</span><span class=w> </span><span class=n>size</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>size</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>size_type</span><span class=w> </span><span class=n>max_size</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>max_size</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>void</span><span class=w> </span><span class=n>clear</span><span class=p>()</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>clear</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>void</span><span class=w> </span><span class=n>resize</span><span class=p>(</span><span class=n>size_type</span><span class=w> </span><span class=n>n</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>resize</span><span class=p>(</span><span class=n>n</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>T</span><span class=o>&amp;</span><span class=w> </span><span class=k>operator</span><span class=p>[](</span><span class=n>size_type</span><span class=w> </span><span class=n>pos</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>[</span><span class=n>pos</span><span class=p>];</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>T</span><span class=o>&amp;</span><span class=w> </span><span class=k>operator</span><span class=p>[](</span><span class=n>size_type</span><span class=w> </span><span class=n>pos</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>[</span><span class=n>pos</span><span class=p>];</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>T</span><span class=o>&amp;</span><span class=w> </span><span class=n>back</span><span class=p>()</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>back</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>T</span><span class=o>&amp;</span><span class=w> </span><span class=n>back</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>back</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>void</span><span class=w> </span><span class=n>push_back</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>T</span><span class=o>&amp;</span><span class=w> </span><span class=n>value</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>push_back</span><span class=p>(</span><span class=n>value</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>void</span><span class=w> </span><span class=n>push_back</span><span class=p>(</span><span class=n>T</span><span class=o>&amp;&amp;</span><span class=w> </span><span class=n>value</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>push_back</span><span class=p>(</span><span class=n>std</span><span class=o>::</span><span class=n>move</span><span class=p>(</span><span class=n>value</span><span class=p>));</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=k>template</span><span class=o>&lt;</span><span class=k>class</span><span class=p>...</span><span class=w> </span><span class=n>Args</span><span class=o>&gt;</span>
<span class=w> </span><span class=kt>void</span><span class=w> </span><span class=n>emplace_back</span><span class=p>(</span><span class=n>Args</span><span class=o>&amp;&amp;</span><span class=w> </span><span class=p>...</span><span class=w> </span><span class=n>args</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>emplace_back</span><span class=p>(</span><span class=n>std</span><span class=o>::</span><span class=n>forward</span><span class=o>&lt;</span><span class=n>Args</span><span class=o>&gt;</span><span class=p>(</span><span class=n>args</span><span class=p>)...);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>void</span><span class=w> </span><span class=n>pop_back</span><span class=p>()</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>pop_back</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=n>insert</span><span class=p>(</span><span class=n>const_iterator</span><span class=w> </span><span class=n>pos</span><span class=p>,</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>T</span><span class=o>&amp;</span><span class=w> </span><span class=n>value</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>insert</span><span class=p>(</span><span class=n>pos</span><span class=p>,</span><span class=w> </span><span class=n>value</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=n>insert</span><span class=p>(</span><span class=n>const_iterator</span><span class=w> </span><span class=n>pos</span><span class=p>,</span><span class=w> </span><span class=n>size_type</span><span class=w> </span><span class=n>count</span><span class=p>,</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>T</span><span class=o>&amp;</span><span class=w> </span><span class=n>value</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>insert</span><span class=p>(</span><span class=n>pos</span><span class=p>,</span><span class=w> </span><span class=n>count</span><span class=p>,</span><span class=w> </span><span class=n>value</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=k>template</span><span class=o>&lt;</span><span class=k>class</span><span class=w> </span><span class=nc>InputIt</span><span class=o>&gt;</span>
<span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=n>insert</span><span class=p>(</span><span class=n>const_iterator</span><span class=w> </span><span class=n>pos</span><span class=p>,</span><span class=w> </span><span class=n>InputIt</span><span class=w> </span><span class=n>first</span><span class=p>,</span><span class=w> </span><span class=n>InputIt</span><span class=w> </span><span class=n>last</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>insert</span><span class=p>(</span><span class=n>pos</span><span class=p>,</span><span class=w> </span><span class=n>first</span><span class=p>,</span><span class=w> </span><span class=n>last</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=n>erase</span><span class=p>(</span><span class=n>const_iterator</span><span class=w> </span><span class=n>pos</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>erase</span><span class=p>(</span><span class=n>pos</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=n>erase</span><span class=p>(</span><span class=n>const_iterator</span><span class=w> </span><span class=n>first</span><span class=p>,</span><span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=n>last</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>erase</span><span class=p>(</span><span class=n>first</span><span class=p>,</span><span class=w> </span><span class=n>last</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>void</span><span class=w> </span><span class=n>swap</span><span class=p>(</span><span class=n>custom_array_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>other</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>swap</span><span class=p>(</span><span class=n>other</span><span class=p>.</span><span class=n>data_</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=k>friend</span><span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=k>operator</span><span class=o>==</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>custom_array_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>lhs</span><span class=p>,</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>custom_array_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>rhs</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>lhs</span><span class=p>.</span><span class=n>data_</span><span class=w> </span><span class=o>==</span><span class=w> </span><span class=n>rhs</span><span class=p>.</span><span class=n>data_</span><span class=p>;</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=k>friend</span><span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=k>operator</span><span class=o>&lt;</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>custom_array_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>lhs</span><span class=p>,</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>custom_array_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>rhs</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>lhs</span><span class=p>.</span><span class=n>data_</span><span class=w> </span><span class=o>&lt;</span><span class=w> </span><span class=n>rhs</span><span class=p>.</span><span class=n>data_</span><span class=p>;</span>
<span class=w> </span><span class=p>}</span>
<span class=p>};</span>
</code></pre></div> </div> <details class=example> <summary>Compiling and using it</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;map&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;nlohmann/json.hpp&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>"custom_array_type.hpp"</span>
<span class=k>using</span><span class=w> </span><span class=n>custom_json</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>nlohmann</span><span class=o>::</span><span class=n>basic_json</span><span class=o>&lt;</span><span class=n>std</span><span class=o>::</span><span class=n>map</span><span class=p>,</span><span class=w> </span><span class=n>custom_array_type</span><span class=o>&gt;</span><span class=p>;</span>
<span class=kt>int</span><span class=w> </span><span class=nf>main</span><span class=p>()</span>
<span class=p>{</span>
<span class=w> </span><span class=n>custom_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>custom_json</span><span class=o>::</span><span class=n>array</span><span class=p>();</span>
<span class=w> </span><span class=n>j</span><span class=p>.</span><span class=n>push_back</span><span class=p>(</span><span class=mi>1</span><span class=p>);</span>
<span class=w> </span><span class=n>j</span><span class=p>.</span><span class=n>push_back</span><span class=p>(</span><span class=mi>2</span><span class=p>);</span>
<span class=w> </span><span class=n>j</span><span class=p>.</span><span class=n>push_back</span><span class=p>(</span><span class=mi>3</span><span class=p>);</span>
<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=n>j</span><span class=p>.</span><span class=n>dump</span><span class=p>()</span><span class=w> </span><span class=o>&lt;&lt;</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>endl</span><span class=p>;</span>
<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=n>std</span><span class=o>::</span><span class=n>boolalpha</span><span class=w> </span><span class=o>&lt;&lt;</span><span class=w> </span><span class=p>(</span><span class=n>custom_json</span><span class=o>::</span><span class=n>parse</span><span class=p>(</span><span class=n>j</span><span class=p>.</span><span class=n>dump</span><span class=p>())</span><span class=w> </span><span class=o>==</span><span class=w> </span><span class=n>j</span><span class=p>)</span><span class=w> </span><span class=o>&lt;&lt;</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>endl</span><span class=p>;</span>
<span class=p>}</span>
</code></pre></div> <p>Output:</p> <div class=highlight><pre><span></span><code><span class=p>[</span><span class=mi>1</span><span class=p>,</span><span class=mi>2</span><span class=p>,</span><span class=mi>3</span><span class=p>]</span>
<span class=kc>true</span>
</code></pre></div> </details> <h3 id=compatible-containers_1>Compatible containers<a class=headerlink href=#compatible-containers_1 title="Permanent link">&para;</a></h3> <table> <thead> <tr> <th>Container</th> <th>Notes</th> </tr> </thead> <tbody> <tr> <td><code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>vector</span></code> (default)</td> <td></td> </tr> <tr> <td><code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>deque</span></code></td> <td>references survive appends, but not insertions elsewhere; see the <code>capacity()</code> note above</td> </tr> <tr> <td><code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>pmr</span><span class=o>::</span><span class=n>vector</span></code></td> <td>through an alias, as the allocator comes from <code>AllocatorType</code> instead</td> </tr> <tr> <td><code>boost::container::vector</code>, <code>deque</code>, <code>devector</code></td> <td></td> </tr> <tr> <td><code>boost::container::stable_vector</code></td> <td>the only one tried that keeps references valid across <em>every</em> insertion</td> </tr> <tr> <td><code>boost::container::small_vector</code>, <code>folly::small_vector</code></td> <td>through an alias that fixes the inline capacity</td> </tr> <tr> <td><code>boost::container::static_vector</code></td> <td>through the same kind of alias, for arrays that stay within the fixed capacity</td> </tr> <tr> <td><code>folly::fbvector</code></td> <td>requires C++20, see the note above</td> </tr> </tbody> </table> <h3 id=containers-that-cannot-be-used_1>Containers that cannot be used<a class=headerlink href=#containers-that-cannot-be-used_1 title="Permanent link">&para;</a></h3> <table> <thead> <tr> <th>Container</th> <th>Reason</th> </tr> </thead> <tbody> <tr> <td><code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>list</span></code></td> <td>no <code>operator[]</code>, and no random-access iterators</td> </tr> <tr> <td><code>eastl::vector</code>, <code>QList</code>, <code>QVector</code></td> <td>no <code>max_size()</code>; they handle the incomplete value type fine</td> </tr> <tr> <td><code>absl::InlinedVector</code></td> <td>requires a complete value type, see the note above</td> </tr> <tr> <td><code>absl::FixedArray</code></td> <td>the size is fixed at construction, so <code>resize</code>, <code>push_back</code>, <code>insert</code> and <code>erase</code> are missing</td> </tr> </tbody> </table> <h2 id=stringtype><code>StringType</code><a class=headerlink href=#stringtype title="Permanent link">&para;</a></h2> <p><code>StringType</code> is used <strong>both</strong> for <abbr title="JavaScript Object Notation">JSON</abbr> string values and for the keys of <abbr title="JavaScript Object Notation">JSON</abbr> objects (<code>string_t</code> and <code>object_t::key_type</code>).</p> <h3 id=always-required_2>Always required<a class=headerlink href=#always-required_2 title="Permanent link">&para;</a></h3> <ul> <li>A member type <code>value_type</code> that is one byte wide and <code>char</code>-compatible. The library stores and processes <abbr title="Unicode Transformation Format">UTF</abbr>-8 encoded <code>char</code> data and hands <code>data()</code> to <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>strtoull</span></code>/<code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>strtoll</span></code>. <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>wstring</span></code>, <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>u16string</span></code>, and <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>u32string</span></code> are <strong>not</strong> valid choices; see the <abbr title="Frequently Asked Questions">FAQ</abbr> on <a href=../../../home/faq/#wide-string-handling>wide string handling</a>.</li> <li>Constructors: default, copy, move, from <code class=highlight><span class=k>const</span><span class=w> </span><span class=kt>char</span><span class=o>*</span></code> (which must not be <code class=highlight><span class=k>explicit</span></code>), from <code class=highlight><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=kt>char</span><span class=o>*</span><span class=p>,</span><span class=w> </span><span class=n>size_type</span><span class=p>)</span></code>, and from <code class=highlight><span class=p>(</span><span class=n>size_type</span><span class=p>,</span><span class=w> </span><span class=kt>char</span><span class=p>)</span></code>; and copy or move assignment.</li> <li>Member functions <code>size()</code>, <code>clear()</code>, <code>resize(n, c)</code>, <code>data()</code>, <code>push_back(char)</code>, and <code>operator[]</code> (const and non-const, returning references). <code>c_str()</code> and <code>back()</code> are <strong>not</strong> rLine truncated
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;ostream&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;string&gt;</span>
<span class=c1>// A minimal, self-contained StringType built around a private std::string.</span>
<span class=c1>// Wraps rather than inherits, so it exposes exactly what the library needs</span>
<span class=c1>// and nothing more of std::string's interface.</span>
<span class=c1>//</span>
<span class=c1>// Covers the "Always required" members, the extras needed for the binary</span>
<span class=c1>// formats, and the extras needed for JSON Pointer / flatten / unflatten /</span>
<span class=c1>// diff. Extending it further (e.g. for std::hash&lt;basic_json&gt; or to_bson) is</span>
<span class=c1>// a matter of adding the extra members listed in the "Required for other</span>
<span class=c1>// functionality" table.</span>
<span class=c1>//</span>
<span class=c1>// See https://json.nlohmann.me/features/types/template_parameters/#stringtype</span>
<span class=k>class</span><span class=w> </span><span class=nc>custom_string_type</span>
<span class=p>{</span>
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=w> </span><span class=n>data_</span><span class=p>;</span>
<span class=w> </span><span class=k>public</span><span class=o>:</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>value_type</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=kt>char</span><span class=p>;</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>size_type</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=o>::</span><span class=n>size_type</span><span class=p>;</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=o>::</span><span class=n>iterator</span><span class=p>;</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=o>::</span><span class=n>const_iterator</span><span class=p>;</span>
<span class=w> </span><span class=k>static</span><span class=w> </span><span class=k>constexpr</span><span class=w> </span><span class=n>size_type</span><span class=w> </span><span class=n>npos</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=o>::</span><span class=n>npos</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_string_type</span><span class=p>()</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_string_type</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>custom_string_type</span><span class=o>&amp;</span><span class=p>)</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_string_type</span><span class=p>(</span><span class=n>custom_string_type</span><span class=o>&amp;&amp;</span><span class=p>)</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_string_type</span><span class=o>&amp;</span><span class=w> </span><span class=k>operator</span><span class=o>=</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>custom_string_type</span><span class=o>&amp;</span><span class=p>)</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_string_type</span><span class=o>&amp;</span><span class=w> </span><span class=k>operator</span><span class=o>=</span><span class=p>(</span><span class=n>custom_string_type</span><span class=o>&amp;&amp;</span><span class=p>)</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=c1>// not explicit: the library relies on being able to hand it a string literal</span>
<span class=w> </span><span class=n>custom_string_type</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=kt>char</span><span class=o>*</span><span class=w> </span><span class=n>s</span><span class=p>)</span><span class=w> </span><span class=o>:</span><span class=w> </span><span class=n>data_</span><span class=p>(</span><span class=n>s</span><span class=p>)</span><span class=w> </span><span class=p>{}</span>
<span class=w> </span><span class=n>custom_string_type</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=kt>char</span><span class=o>*</span><span class=w> </span><span class=n>s</span><span class=p>,</span><span class=w> </span><span class=n>size_type</span><span class=w> </span><span class=n>count</span><span class=p>)</span><span class=w> </span><span class=o>:</span><span class=w> </span><span class=n>data_</span><span class=p>(</span><span class=n>s</span><span class=p>,</span><span class=w> </span><span class=n>count</span><span class=p>)</span><span class=w> </span><span class=p>{}</span>
<span class=w> </span><span class=n>custom_string_type</span><span class=p>(</span><span class=n>size_type</span><span class=w> </span><span class=n>count</span><span class=p>,</span><span class=w> </span><span class=kt>char</span><span class=w> </span><span class=n>ch</span><span class=p>)</span><span class=w> </span><span class=o>:</span><span class=w> </span><span class=n>data_</span><span class=p>(</span><span class=n>count</span><span class=p>,</span><span class=w> </span><span class=n>ch</span><span class=p>)</span><span class=w> </span><span class=p>{}</span>
<span class=w> </span><span class=n>size_type</span><span class=w> </span><span class=n>size</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>size</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=n>empty</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>empty</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>void</span><span class=w> </span><span class=n>clear</span><span class=p>()</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>clear</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>void</span><span class=w> </span><span class=n>resize</span><span class=p>(</span><span class=n>size_type</span><span class=w> </span><span class=n>n</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>resize</span><span class=p>(</span><span class=n>n</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>void</span><span class=w> </span><span class=n>resize</span><span class=p>(</span><span class=n>size_type</span><span class=w> </span><span class=n>n</span><span class=p>,</span><span class=w> </span><span class=kt>char</span><span class=w> </span><span class=n>c</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>resize</span><span class=p>(</span><span class=n>n</span><span class=p>,</span><span class=w> </span><span class=n>c</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>void</span><span class=w> </span><span class=n>reserve</span><span class=p>(</span><span class=n>size_type</span><span class=w> </span><span class=n>n</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>reserve</span><span class=p>(</span><span class=n>n</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=c1>// must stay null-terminated -- the parser hands this to std::strtoull &amp;</span>
<span class=w> </span><span class=c1>// friends; std::string::data() has guaranteed that since C++11</span>
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=kt>char</span><span class=o>*</span><span class=w> </span><span class=n>data</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>data</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>void</span><span class=w> </span><span class=n>push_back</span><span class=p>(</span><span class=kt>char</span><span class=w> </span><span class=n>c</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>push_back</span><span class=p>(</span><span class=n>c</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>char</span><span class=o>&amp;</span><span class=w> </span><span class=k>operator</span><span class=p>[](</span><span class=n>size_type</span><span class=w> </span><span class=n>pos</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>[</span><span class=n>pos</span><span class=p>];</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>char</span><span class=w> </span><span class=k>operator</span><span class=p>[](</span><span class=n>size_type</span><span class=w> </span><span class=n>pos</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>[</span><span class=n>pos</span><span class=p>];</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>custom_string_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>append</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=kt>char</span><span class=o>*</span><span class=w> </span><span class=n>s</span><span class=p>,</span><span class=w> </span><span class=n>size_type</span><span class=w> </span><span class=n>count</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>append</span><span class=p>(</span><span class=n>s</span><span class=p>,</span><span class=w> </span><span class=n>count</span><span class=p>);</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=o>*</span><span class=k>this</span><span class=p>;</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>custom_string_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>append</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>custom_string_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>other</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>append</span><span class=p>(</span><span class=n>other</span><span class=p>.</span><span class=n>data_</span><span class=p>);</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=o>*</span><span class=k>this</span><span class=p>;</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>size_type</span><span class=w> </span><span class=n>find_first_of</span><span class=p>(</span><span class=kt>char</span><span class=w> </span><span class=n>c</span><span class=p>,</span><span class=w> </span><span class=n>size_type</span><span class=w> </span><span class=n>pos</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=mi>0</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>find_first_of</span><span class=p>(</span><span class=n>c</span><span class=p>,</span><span class=w> </span><span class=n>pos</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=n>begin</span><span class=p>()</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>begin</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=n>end</span><span class=p>()</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>end</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=n>begin</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>begin</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=n>end</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>end</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=k>friend</span><span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=k>operator</span><span class=o>==</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>custom_string_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>lhs</span><span class=p>,</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>custom_string_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>rhs</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>lhs</span><span class=p>.</span><span class=n>data_</span><span class=w> </span><span class=o>==</span><span class=w> </span><span class=n>rhs</span><span class=p>.</span><span class=n>data_</span><span class=p>;</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=k>friend</span><span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=k>operator</span><span class=o>&lt;</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>custom_string_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>lhs</span><span class=p>,</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>custom_string_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>rhs</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>lhs</span><span class=p>.</span><span class=n>data_</span><span class=w> </span><span class=o>&lt;</span><span class=w> </span><span class=n>rhs</span><span class=p>.</span><span class=n>data_</span><span class=p>;</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=c1>// not required by the library itself, but dump() returns a custom_string_type</span>
<span class=w> </span><span class=c1>// and this makes `std::cout &lt;&lt; j.dump()` work as expected</span>
<span class=w> </span><span class=k>friend</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>ostream</span><span class=o>&amp;</span><span class=w> </span><span class=k>operator</span><span class=o>&lt;&lt;</span><span class=p>(</span><span class=n>std</span><span class=o>::</span><span class=n>ostream</span><span class=o>&amp;</span><span class=w> </span><span class=n>os</span><span class=p>,</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>custom_string_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>s</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>os</span><span class=w> </span><span class=o>&lt;&lt;</span><span class=w> </span><span class=n>s</span><span class=p>.</span><span class=n>data_</span><span class=p>;</span>
<span class=w> </span><span class=p>}</span>
<span class=p>};</span>
</code></pre></div> </div> <details class=example> <summary>Compiling and using it</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;map&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;vector&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;nlohmann/json.hpp&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>"custom_string_type.hpp"</span>
<span class=k>using</span><span class=w> </span><span class=n>custom_json</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>nlohmann</span><span class=o>::</span><span class=n>basic_json</span><span class=o>&lt;</span><span class=n>std</span><span class=o>::</span><span class=n>map</span><span class=p>,</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>vector</span><span class=p>,</span><span class=w> </span><span class=n>custom_string_type</span><span class=o>&gt;</span><span class=p>;</span>
<span class=kt>int</span><span class=w> </span><span class=nf>main</span><span class=p>()</span>
<span class=p>{</span>
<span class=w> </span><span class=n>custom_json</span><span class=w> </span><span class=n>j</span><span class=p>;</span>
<span class=w> </span><span class=n>j</span><span class=p>[</span><span class=s>"pi"</span><span class=p>]</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=mf>3.141</span><span class=p>;</span>
<span class=w> </span><span class=n>j</span><span class=p>[</span><span class=s>"happy"</span><span class=p>]</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=n>j</span><span class=p>[</span><span class=s>"list"</span><span class=p>]</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=p>{</span><span class=mi>1</span><span class=p>,</span><span class=w> </span><span class=mi>2</span><span class=p>,</span><span class=w> </span><span class=mi>3</span><span class=p>};</span>
<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=n>j</span><span class=p>.</span><span class=n>dump</span><span class=p>(</span><span class=mi>2</span><span class=p>)</span><span class=w> </span><span class=o>&lt;&lt;</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>endl</span><span class=p>;</span>
<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=n>std</span><span class=o>::</span><span class=n>boolalpha</span><span class=w> </span><span class=o>&lt;&lt;</span><span class=w> </span><span class=p>(</span><span class=n>custom_json</span><span class=o>::</span><span class=n>parse</span><span class=p>(</span><span class=n>j</span><span class=p>.</span><span class=n>dump</span><span class=p>())</span><span class=w> </span><span class=o>==</span><span class=w> </span><span class=n>j</span><span class=p>)</span><span class=w> </span><span class=o>&lt;&lt;</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>endl</span><span class=p>;</span>
<span class=p>}</span>
</code></pre></div> <p>Output:</p> <div class=highlight><pre><span></span><code><span class=p>{</span>
<span class=w> </span><span class=nt>"happy"</span><span class=p>:</span><span class=w> </span><span class=kc>true</span><span class=p>,</span>
<span class=w> </span><span class=nt>"list"</span><span class=p>:</span><span class=w> </span><span class=p>[</span>
<span class=w> </span><span class=mi>1</span><span class=p>,</span>
<span class=w> </span><span class=mi>2</span><span class=p>,</span>
<span class=w> </span><span class=mi>3</span>
<span class=w> </span><span class=p>],</span>
<span class=w> </span><span class=nt>"pi"</span><span class=p>:</span><span class=w> </span><span class=mf>3.141</span>
<span class=p>}</span>
<span class=kc>true</span>
</code></pre></div> </details> <h2 id=booleantype><code>BooleanType</code><a class=headerlink href=#booleantype title="Permanent link">&para;</a></h2> <p><code>boolean_t</code> is stored <strong>directly</strong> inside <code>basic_json</code>, as a member of an anonymous union.</p> <h3 id=always-required_3>Always required<a class=headerlink href=#always-required_3 title="Permanent link">&para;</a></h3> <ul> <li>A literal type that is trivially default-constructible, trivially copyable, and trivially destructible; otherwise the union's special member functions are deleted.</li> <li><strong>Implicitly</strong> convertible from <code class=highlight><span class=kt>bool</span></code> -- an <code class=highlight><span class=k>explicit</span></code> constructor is not enough, because the <code>to_json</code> overload for a custom <code>BooleanType</code> is constrained on <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>is_convertible</span></code> -- and contextually convertible to <code class=highlight><span class=kt>bool</span></code> (here an <code class=highlight><span class=k>explicit</span><span class=w> </span><span class=k>operator</span><span class=w> </span><span class=kt>bool</span></code> is fine).</li> <li>Comparison operators <code>==</code>, <code>!=</code>, <code>&lt;</code>, <code>&lt;=</code>, <code>&gt;</code>, <code>&gt;=</code> (or <code>&lt;=&gt;</code>).</li> <li>Convertible from and to <code class=highlight><span class=kt>bool</span></code> through the serializer, because <a href=../../../api/basic_json/get/ ><code>get&lt;bool&gt;()</code></a> is used internally.</li> </ul> <p>There is little reason to use anything other than <code class=highlight><span class=kt>bool</span></code> here.</p> <h3 id=compatible-types_1>Compatible types<a class=headerlink href=#compatible-types_1 title="Permanent link">&para;</a></h3> <p><code class=highlight><span class=kt>bool</span></code> is the only usable choice. Another trivially copyable type that is implicitly convertible to and from <code class=highlight><span class=kt>bool</span></code> -- <code class=highlight><span class=n>std</span><span class=o>::</span><span class=kt>uint8_t</span></code>, say -- does compile, and <abbr title="JavaScript Object Notation">JSON</abbr> booleans still round-trip, but the type then serves as both <code>boolean_t</code> and an ordinary integer: <code>basic_json</code> can no longer be constructed or assigned from a <code class=highlight><span class=n>std</span><span class=o>::</span><span class=kt>uint8_t</span></code> at all (the boolean and unsigned-integer <code>to_json</code> overloads become ambiguous), and <a href=../../../api/basic_json/get/ ><code>get&lt;std::uint8_t&gt;()</code></a> on a number throws <a href=../../../home/exceptions/#jsonexceptiontype_error302><code>type_error.302</code></a> instead of returning the value.</p> <h2 id=numberintegertype-and-numberunsignedtype><code>NumberIntegerType</code> and <code>NumberUnsignedType</code><a class=headerlink href=#numberintegertype-and-numberunsignedtype title="Permanent link">&para;</a></h2> <p>Both types are stored <strong>directly</strong> inside <code>basic_json</code>'s union.</p> <h3 id=always-required_4>Always required<a class=headerlink href=#always-required_4 title="Permanent link">&para;</a></h3> <ul> <li><code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>is_integral</span></code> must be satisfied: <code>NumberIntegerType</code> must be a <strong>signed</strong> integer type, <code>NumberUnsignedType</code> an <strong>unsigned</strong> integer type. Class types are not supported -- among others, the constructors taking integer values are constrained on <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>is_integral</span></code>.</li> <li>Trivially default-constructible, trivially copyable, and trivially destructible (union member).</li> <li><code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>numeric_limits</span></code> must be specialized for both types.</li> <li><code>NumberUnsignedType</code> must be able to represent the absolute value of every <code>NumberIntegerType</code> value; serialization of negative numbers converts the value to <code>NumberUnsignedType</code>. A <code class=highlight><span class=k>static_assert</span></code> requires it to be at least as wide as <code>NumberIntegerType</code>, which is what that amounts to for the standard integer types.</li> <li>Both types must fit into the internal 64-character number buffer used by <a href=../../../api/basic_json/dump/ ><code>dump</code></a>, which is the case for all standard integer types.</li> <li><a href=../../../api/basic_json/std_hash/ ><code>std::hash&lt;basic_json&gt;</code></a> additionally requires <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>hash</span></code> specializations.</li> </ul> <h3 id=notes_1>Line truncated
</code></pre></div> <h3 id=always-required_8>Always required<a class=headerlink href=#always-required_8 title="Permanent link">&para;</a></h3> <ul> <li>A non-<code>final</code> class type -- <a href=../../../api/byte_container_with_subtype/ ><code>byte_container_with_subtype</code></a> derives from it publicly.</li> <li>A member type <code>value_type</code> that is <strong>exactly one byte</strong> wide (e.g., <code class=highlight><span class=n>std</span><span class=o>::</span><span class=kt>uint8_t</span></code>, <code class=highlight><span class=kt>char</span></code>, or <code class=highlight><span class=n>std</span><span class=o>::</span><span class=kt>byte</span></code>). Readers and writers reinterpret the container's storage as raw bytes, so a wider <code>value_type</code> is rejected with a <code class=highlight><span class=k>static_assert</span></code>.</li> <li>Contiguous storage: the binary readers <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>memcpy</span></code> into <code class=highlight><span class=o>&amp;</span><span class=n>binary</span><span class=p>[</span><span class=n>n</span><span class=p>]</span></code>, the writers <code>reinterpret_cast</code> <code>data()</code>. <code class=highlight><span class=n>data</span><span class=p>()</span><span class=w> </span><span class=o>+</span><span class=w> </span><span class=n>n</span></code> would do for the readers too, but they share one helper with <a href=#stringtype><code>StringType</code></a>, whose non-<code class=highlight><span class=k>const</span></code> <code>data()</code> is C++17 and later only.</li> <li>Default-constructible, copy-constructible, and move-constructible.</li> <li>Member functions <code>size()</code>, <code>empty()</code>, <code>data()</code>, <code>resize()</code>, <code>operator[]</code>, <code>back()</code>, <code>begin()</code>, <code>end()</code>, <code>cbegin()</code>, and <code>cend()</code> with random-access iterators, and <code>insert(pos, first, last)</code>, which the <abbr title="Concise Binary Object Representation">CBOR</abbr> reader uses to join the chunks of an indefinite-length byte string. <code>push_back()</code> is <strong>not</strong> required.</li> <li>Comparison operators: <code>==</code> is used by <a href=../../../api/byte_container_with_subtype/ ><code>byte_container_with_subtype</code></a>, the relational operators by <a href=../../../api/basic_json/operator_le/ ><code>basic_json</code>'s comparison operators</a>.</li> </ul> <h3 id=required-for-individual-functions_1>Required for individual functions<a class=headerlink href=#required-for-individual-functions_1 title="Permanent link">&para;</a></h3> <ul> <li><code>clear()</code>, for <a href=../../../api/basic_json/clear/ ><code>basic_json::clear()</code></a>.</li> </ul> <p><code>max_size()</code>, <code>at()</code>, <code>reserve()</code>, <code>erase()</code>, <code>pop_back()</code>, and <code>emplace_back()</code> are <strong>not</strong> used at all.</p> <p>See <a href=../../../api/basic_json/binary_t/ ><code>binary_t</code></a> for how a non-default <code>BinaryType</code> changes the meaning of assigning such a container to a <code>basic_json</code> value.</p> <div class="admonition tip"> <p class=admonition-title>Reference implementation</p> <p><code>docs/mkdocs/docs/examples/custom_binary_type.hpp</code> wraps a private <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=kt>uint8_t</span><span class=o>&gt;</span></code> and satisfies every requirement above -- a good starting point for a custom <code>BinaryType</code>.</p> <div class=highlight><pre><span></span><code><span class=cp>#pragma once</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;cstdint&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;initializer_list&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;vector&gt;</span>
<span class=c1>// A minimal, self-contained BinaryType built around a private std::vector.</span>
<span class=c1>// See https://json.nlohmann.me/features/types/template_parameters/#binarytype</span>
<span class=k>class</span><span class=w> </span><span class=nc>custom_binary_type</span>
<span class=p>{</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>vector_t</span><span class=w> </span><span class=o>=</span><span class=w> </span><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=kt>uint8_t</span><span class=o>&gt;</span><span class=p>;</span>
<span class=w> </span><span class=n>vector_t</span><span class=w> </span><span class=n>data_</span><span class=p>;</span>
<span class=w> </span><span class=k>public</span><span class=o>:</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>value_type</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>vector_t</span><span class=o>::</span><span class=n>value_type</span><span class=p>;</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>size_type</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>vector_t</span><span class=o>::</span><span class=n>size_type</span><span class=p>;</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>vector_t</span><span class=o>::</span><span class=n>iterator</span><span class=p>;</span>
<span class=w> </span><span class=k>using</span><span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>vector_t</span><span class=o>::</span><span class=n>const_iterator</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_binary_type</span><span class=p>()</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_binary_type</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>custom_binary_type</span><span class=o>&amp;</span><span class=p>)</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_binary_type</span><span class=p>(</span><span class=n>custom_binary_type</span><span class=o>&amp;&amp;</span><span class=p>)</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_binary_type</span><span class=o>&amp;</span><span class=w> </span><span class=k>operator</span><span class=o>=</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>custom_binary_type</span><span class=o>&amp;</span><span class=p>)</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=n>custom_binary_type</span><span class=o>&amp;</span><span class=w> </span><span class=k>operator</span><span class=o>=</span><span class=p>(</span><span class=n>custom_binary_type</span><span class=o>&amp;&amp;</span><span class=p>)</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>default</span><span class=p>;</span>
<span class=w> </span><span class=k>template</span><span class=o>&lt;</span><span class=k>class</span><span class=w> </span><span class=nc>InputIt</span><span class=o>&gt;</span>
<span class=w> </span><span class=n>custom_binary_type</span><span class=p>(</span><span class=n>InputIt</span><span class=w> </span><span class=n>first</span><span class=p>,</span><span class=w> </span><span class=n>InputIt</span><span class=w> </span><span class=n>last</span><span class=p>)</span><span class=w> </span><span class=o>:</span><span class=w> </span><span class=n>data_</span><span class=p>(</span><span class=n>first</span><span class=p>,</span><span class=w> </span><span class=n>last</span><span class=p>)</span><span class=w> </span><span class=p>{}</span>
<span class=w> </span><span class=c1>// so basic_json::binary({0x01, 0x02}) can build one directly</span>
<span class=w> </span><span class=n>custom_binary_type</span><span class=p>(</span><span class=n>std</span><span class=o>::</span><span class=n>initializer_list</span><span class=o>&lt;</span><span class=n>std</span><span class=o>::</span><span class=kt>uint8_t</span><span class=o>&gt;</span><span class=w> </span><span class=n>init</span><span class=p>)</span><span class=w> </span><span class=o>:</span><span class=w> </span><span class=n>data_</span><span class=p>(</span><span class=n>init</span><span class=p>)</span><span class=w> </span><span class=p>{}</span>
<span class=w> </span><span class=n>size_type</span><span class=w> </span><span class=n>size</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>size</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=n>empty</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>empty</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>void</span><span class=w> </span><span class=n>clear</span><span class=p>()</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>clear</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=kt>void</span><span class=w> </span><span class=n>resize</span><span class=p>(</span><span class=n>size_type</span><span class=w> </span><span class=n>n</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>resize</span><span class=p>(</span><span class=n>n</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=c1>// read-only is enough: the writers only ever read from a binary value</span>
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=kt>uint8_t</span><span class=o>*</span><span class=w> </span><span class=n>data</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>data</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=kt>uint8_t</span><span class=o>&amp;</span><span class=w> </span><span class=k>operator</span><span class=p>[](</span><span class=n>size_type</span><span class=w> </span><span class=n>pos</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>[</span><span class=n>pos</span><span class=p>];</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=kt>uint8_t</span><span class=w> </span><span class=k>operator</span><span class=p>[](</span><span class=n>size_type</span><span class=w> </span><span class=n>pos</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>[</span><span class=n>pos</span><span class=p>];</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=kt>uint8_t</span><span class=o>&amp;</span><span class=w> </span><span class=n>back</span><span class=p>()</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>back</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=kt>uint8_t</span><span class=w> </span><span class=n>back</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>back</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=n>begin</span><span class=p>()</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>begin</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=n>end</span><span class=p>()</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>end</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=n>begin</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>begin</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=n>end</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>end</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=n>cbegin</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>cbegin</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=n>const_iterator</span><span class=w> </span><span class=n>cend</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=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>cend</span><span class=p>();</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=k>template</span><span class=o>&lt;</span><span class=k>class</span><span class=w> </span><span class=nc>InputIt</span><span class=o>&gt;</span>
<span class=w> </span><span class=n>iterator</span><span class=w> </span><span class=n>insert</span><span class=p>(</span><span class=n>const_iterator</span><span class=w> </span><span class=n>pos</span><span class=p>,</span><span class=w> </span><span class=n>InputIt</span><span class=w> </span><span class=n>first</span><span class=p>,</span><span class=w> </span><span class=n>InputIt</span><span class=w> </span><span class=n>last</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>data_</span><span class=p>.</span><span class=n>insert</span><span class=p>(</span><span class=n>pos</span><span class=p>,</span><span class=w> </span><span class=n>first</span><span class=p>,</span><span class=w> </span><span class=n>last</span><span class=p>);</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=k>friend</span><span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=k>operator</span><span class=o>==</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>custom_binary_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>lhs</span><span class=p>,</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>custom_binary_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>rhs</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>lhs</span><span class=p>.</span><span class=n>data_</span><span class=w> </span><span class=o>==</span><span class=w> </span><span class=n>rhs</span><span class=p>.</span><span class=n>data_</span><span class=p>;</span>
<span class=w> </span><span class=p>}</span>
<span class=w> </span><span class=k>friend</span><span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=k>operator</span><span class=o>&lt;</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>custom_binary_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>lhs</span><span class=p>,</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>custom_binary_type</span><span class=o>&amp;</span><span class=w> </span><span class=n>rhs</span><span class=p>)</span>
<span class=w> </span><span class=p>{</span>
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=n>lhs</span><span class=p>.</span><span class=n>data_</span><span class=w> </span><span class=o>&lt;</span><span class=w> </span><span class=n>rhs</span><span class=p>.</span><span class=n>data_</span><span class=p>;</span>
<span class=w> </span><span class=p>}</span>
<span class=p>};</span>
</code></pre></div> </div> <details class=example> <summary>Compiling and using it</summary> <div class=highlight><pre><span></span><code><span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;cstdint&gt;</span>
<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;map&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;string&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;vector&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;nlohmann/json.hpp&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>"custom_binary_type.hpp"</span>
<span class=k>using</span><span class=w> </span><span class=n>custom_json</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>nlohmann</span><span class=o>::</span><span class=n>basic_json</span><span class=o>&lt;</span><span class=n>std</span><span class=o>::</span><span class=n>map</span><span class=p>,</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>vector</span><span class=p>,</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=p>,</span><span class=w> </span><span class=kt>bool</span><span class=p>,</span>
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=kt>int64_t</span><span class=p>,</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=kt>uint64_t</span><span class=p>,</span><span class=w> </span><span class=kt>double</span><span class=p>,</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>allocator</span><span class=p>,</span>
<span class=w> </span><span class=n>nlohmann</span><span class=o>::</span><span class=n>adl_serializer</span><span class=p>,</span><span class=w> </span><span class=n>custom_binary_type</span><span class=o>&gt;</span><span class=p>;</span>
<span class=kt>int</span><span class=w> </span><span class=nf>main</span><span class=p>()</span>
<span class=p>{</span>
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=k>auto</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>custom_json</span><span class=o>::</span><span class=n>binary</span><span class=p>({</span><span class=mh>0x01</span><span class=p>,</span><span class=w> </span><span class=mh>0x02</span><span class=p>,</span><span class=w> </span><span class=mh>0x03</span><span class=p>});</span>
<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=n>j</span><span class=p>.</span><span class=n>dump</span><span class=p>()</span><span class=w> </span><span class=o>&lt;&lt;</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>endl</span><span class=p>;</span>
<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=n>std</span><span class=o>::</span><span class=n>boolalpha</span><span class=w> </span><span class=o>&lt;&lt;</span><span class=w> </span><span class=p>(</span><span class=n>custom_json</span><span class=o>::</span><span class=n>from_cbor</span><span class=p>(</span><span class=n>custom_json</span><span class=o>::</span><span class=n>to_cbor</span><span class=p>(</span><span class=n>j</span><span class=p>))</span><span class=w> </span><span class=o>==</span><span class=w> </span><span class=n>j</span><span class=p>)</span><span class=w> </span><span class=o>&lt;&lt;</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>endl</span><span class=p>;</span>
<span class=p>}</span>
</code></pre></div> <p>Output:</p> <div class=highlight><pre><span></span><code><span class=p>{</span><span class=nt>"bytes"</span><span class=p>:[</span><span class=mi>1</span><span class=p>,</span><span class=mi>2</span><span class=p>,</span><span class=mi>3</span><span class=p>],</span><span class=nt>"subtype"</span><span class=p>:</span><span class=kc>null</span><span class=p>}</span>
<span class=kc>true</span>
</code></pre></div> </details> <h3 id=compatible-containers_2>Compatible containers<a class=headerlink href=#compatible-containers_2 title="Permanent link">&para;</a></h3> <table> <thead> <tr> <th>Container</th> <th>Notes</th> </tr> </thead> <tbody> <tr> <td><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=kt>uint8_t</span><span class=o>&gt;</span></code> (default)</td> <td></td> </tr> <tr> <td><code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>vector</span><span class=o>&lt;</span><span class=kt>char</span><span class=o>&gt;</span></code>, <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=kt>byte</span><span class=o>&gt;</span></code></td> <td><code>dump()</code> writes the bytes as 0..255 whichever is used</td> </tr> <tr> <td><code>boost::container::vector&lt;std::uint8_t&gt;</code>, <code>boost::container::small_vector&lt;std::uint8_t, N&gt;</code></td> <td></td> </tr> <tr> <td><code>absl::InlinedVector&lt;std::uint8_t, N&gt;</code></td> <td>usable here, unlike as an <code>ArrayType</code>, because the value type is complete</td> </tr> <tr> <td><code>eastl::vector&lt;std::uint8_t&gt;</code></td> <td>usable here, unlike as an <code>ArrayType</code>, because <code>max_size()</code> is not needed</td> </tr> <tr> <td><code>folly::fbvector&lt;std::uint8_t&gt;</code></td> <td>requires C++20, see the note above</td> </tr> </tbody> </table> <h3 id=containers-that-cannot-be-used_2>Containers that cannot be used<a class=headerlink href=#containers-that-cannot-be-used_2 title="Permanent link">&para;</a></h3> <table> <thead> <tr> <th>Container</th> <th>Reason</th> </tr> </thead> <tbody> <tr> <td><code>QByteArray</code></td> <td>no <code>empty()</code> (it spells that <code>isEmpty()</code>); its <code>insert</code> takes an index rather than an iterator; and it converts to <code>string_t</code>, which makes <code>to_json</code> ambiguous between a string and a binary value</td> </tr> <tr> <td><code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>string</span></code></td> <td><code>binary_t::container_type</code> and <code>string_t</code> would be the same type, so the two <a href=../../../api/basic_json/swap/ ><code>swap</code></a> overloads collide and <code>basic_json</code> cannot be instantiated at all</td> </tr> <tr> <td><code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>deque</span><span class=o>&lt;</span><span class=n>std</span><span class=o>::</span><span class=kt>uint8_t</span><span class=o>&gt;</span></code></td> <td>storage is not contiguous, so there is no <code>data()</code></td> </tr> <tr> <td>containers whose <code>value_type</code> is wider than one byte</td> <td>see above -- accepted by the compiler, wrong at runtime</td> </tr> </tbody> </table> <h2 id=custombaseclass><code>CustomBaseClass</code><a class=headerlink href=#custombaseclass title="Permanent link">&para;</a></h2> <p><code>CustomBaseClass</code> is an extension point: unless it is <code class=highlight><span class=kt>void</span></code> (the default, which selects the empty <code>nlohmann::json_default_base</code>), <code>basic_json</code> publicly derives from it.</p> <h3 id=always-required_9>Always required<a class=headerlink href=#always-required_9 title="Permanent link">&para;</a></h3> <ul> <li>A non-<code>final</code>, default-constructible class type.</li> <li><code>basic_json</code> is copy-/move-constructible and copy-/move-assignable only if <code>CustomBaseClass</code> is.</li> </ul> <h3 id=notes_2>Notes<a class=headerlink href=#notes_2 title="Permanent link">&para;</a></h3> <p><code>basic_json</code> is documented to be a <a href="https://en.cppreference.com/w/cpp/named_req/StandardLayoutType">StandardLayoutType</a>. Because <code>basic_json</code> has non-static data members of its own, a <code>CustomBaseClass</code> with non-static data members forfeits this guarantee.</p> <p>Note the namespace of <code>CustomBaseClass</code> becomes an associated namespace of <code>basic_json</code> for the purpose of argument-dependent lookup.</p> <p>See <a href=../../../api/basic_json/json_base_class_t/ ><code>json_base_class_t</code></a> for an example.</p> <h3 id=compatible-types_6>Compatible types<a class=headerlink href=#compatible-types_6 title="Permanent link">&para;</a></h3> <table> <thead> <tr> <th>Type</th> <th>Support</th> </tr> </thead> <tbody> <tr> <td><code class=highlight><span class=kt>void</span></code> (default)</td> <td>an empty base class is used; no effect on <code>basic_json</code></td> </tr> <tr> <td>any default-constructible, non-<code>final</code> class</td> <td>full; see <a href=../../../api/basic_json/json_base_class_t/ ><code>json_base_class_t</code></a></td> </tr>Line truncated
File diff suppressed because it is too large. Load diff