This commit is contained in:
nlohmann committed 2026-10-27 12:14:00 +00:00
1 parent b36f8a9821
commit 11a863958e
1180 files changed
+14211 -6025

No files matched your search

+3 -3
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=description content="JSON for Modern C++ is a header-only C++11 library that makes JSON a first-class data type."><meta name=author content="Niels Lohmann"><link href="https://json.nlohmann.me/features/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=../../css/custom.css><link rel=stylesheet href=../../css/brand.css><link rel=stylesheet href=../../css/fig-sax.css><link rel=stylesheet href=../../css/fig-jsonview.css><link rel=stylesheet href=../../css/fig-exceptions.css><link rel=stylesheet href=../../css/fig-pointer.css><link rel=stylesheet href=../../css/fig-charts.css><link rel=stylesheet href=../../css/fig-integration.css><link rel=stylesheet href=../../css/fig-macros.css><script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script></head> <body dir=ltr data-md-color-scheme=default data-md-color-primary=custom data-md-color-accent=custom> <input class=md-toggle data-md-toggle=drawer type=checkbox id=__drawer autocomplete=off> <input class=md-toggle data-md-toggle=search type=checkbox id=__search autocomplete=off> <label class=md-overlay for=__drawer></label> <div data-md-component=skip> <a href=#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> <img src=../../images/wordmark-header.svg alt=logo> </a> <label class="md-header__button md-icon" for=__drawer> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg> </label> <div class=md-header__title data-md-component=header-title> <div class=md-header__ellipsis> <div class=md-header__topic> <span class=md-ellipsis> JSON for Modern C++ </span> </div> <div class=md-header__topic data-md-component=header-topic> <span class=md-ellipsis> 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=custom data-md-color-accent=custom aria-label="Switch to dark mode" type=radio name=__palette id=__palette_0> <label class="md-header__button md-icon" title="Switch to dark mode" for=__palette_1 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> <input class=md-option data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme=slate data-md-color-primary=custom data-md-color-accent=custom aria-label="Switch to light mode" type=radio name=__palette id=__palette_1> <label class="md-header__button md-icon" title="Switch to light mode" for=__palette_0 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> </form> <script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script> <label class="md-header__button md-icon" for=__search> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79lLine truncated
class value_t {
&lt;&lt;enumeration&gt;&gt;
@@ -39,7 +39,7 @@ class basic_json {
}
basic_json .. json_value
basic_json .. value_t</code></pre> <h2 id=template-arguments>Template arguments<a class=headerlink href=#template-arguments title="Permanent link">&para;</a></h2> <p>The data types to store a <abbr title="JavaScript Object Notation">JSON</abbr> value are derived from the template arguments passed to class <code>basic_json</code>:</p> <div class=highlight><pre><span></span><code><span class=k>template</span><span class=o>&lt;</span>
basic_json .. value_t</code></pre> <p class=nj-caption>Storage of a <code>basic_json</code> value: the enumeration <code>value_t</code> holds the type, and the union <code>json_value</code> holds the value, as a pointer for objects, arrays, strings, and binary values and directly for booleans and numbers.</p> <h2 id=template-arguments>Template arguments<a class=headerlink href=#template-arguments title="Permanent link">&para;</a></h2> <p>The data types to store a <abbr title="JavaScript Object Notation">JSON</abbr> value are derived from the template arguments passed to class <code>basic_json</code>:</p> <div class=highlight><pre><span></span><code><span class=k>template</span><span class=o>&lt;</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=p>,</span><span class=w> </span><span class=k>typename</span><span class=w> </span><span class=nc>V</span><span class=p>,</span><span class=w> </span><span class=k>typename</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=k>class</span><span class=w> </span><span class=nc>ObjectType</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=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=p>,</span><span class=w> </span><span class=k>typename</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=k>class</span><span class=w> </span><span class=nc>ArrayType</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=p>,</span>
<span class=w> </span><span class=k>class</span><span class=w> </span><span class=nc>StringType</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=p>,</span>
@@ -81,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 type 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 type 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 represLine 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 type 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 type 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 represLine truncated
+14 -5
View File
@@ -64,6 +64,8 @@ basic_json .. json_value
basic_json .. value_t
```
Storage of a `basic_json` value: the enumeration `value_t` holds the type, and the union `json_value` holds the value, as a pointer for objects, arrays, strings, and binary values and directly for booleans and numbers.
## Template arguments
The data types to store a JSON value are derived from the template arguments passed to class `basic_json`:
@@ -280,8 +282,15 @@ Integer number values, unsigned integer number values, and floating-point number
## See also
- [Number handling](https://json.nlohmann.me/features/types/number_handling/index.md) - how numbers are stored and converted
- [Template parameter requirements](https://json.nlohmann.me/features/types/template_parameters/index.md)
- [**basic_json**](https://json.nlohmann.me/api/basic_json/index.md) - the class template and its member types
- [**type**](https://json.nlohmann.me/api/basic_json/type/index.md) and [**value_t**](https://json.nlohmann.me/api/basic_json/value_t/index.md) - query the type of a value
- [**object_t**](https://json.nlohmann.me/api/basic_json/object_t/index.md), [**array_t**](https://json.nlohmann.me/api/basic_json/array_t/index.md), [**string_t**](https://json.nlohmann.me/api/basic_json/string_t/index.md), [**number_integer_t**](https://json.nlohmann.me/api/basic_json/number_integer_t/index.md), [**number_float_t**](https://json.nlohmann.me/api/basic_json/number_float_t/index.md) - the underlying types
- [Object order](https://json.nlohmann.me/features/object_order/index.md)
- [Template parameter requirements](https://json.nlohmann.me/features/types/template_parameters/index.md) - what the template parameters of `basic_json` must provide
- [`basic_json`](https://json.nlohmann.me/api/basic_json/index.md) - the class template and its member types
- [`type`](https://json.nlohmann.me/api/basic_json/type/index.md) - and [`value_t`](https://json.nlohmann.me/api/basic_json/value_t/index.md) - query the type of a value
- [`object_t`](https://json.nlohmann.me/api/basic_json/object_t/index.md), [`array_t`](https://json.nlohmann.me/api/basic_json/array_t/index.md), [`string_t`](https://json.nlohmann.me/api/basic_json/string_t/index.md), [`number_integer_t`](https://json.nlohmann.me/api/basic_json/number_integer_t/index.md), [`number_float_t`](https://json.nlohmann.me/api/basic_json/number_float_t/index.md) - the underlying types
- [Object order](https://json.nlohmann.me/features/object_order/index.md) - how object keys are ordered
- [`json`](https://json.nlohmann.me/api/json/index.md) - the default JSON type
- [`boolean_t`](https://json.nlohmann.me/api/basic_json/boolean_t/index.md) - the underlying boolean type
- [`number_unsigned_t`](https://json.nlohmann.me/api/basic_json/number_unsigned_t/index.md) - the underlying unsigned integer type
- [`is_primitive`](https://json.nlohmann.me/api/basic_json/is_primitive/index.md) - and the other `is_*` functions query the type
- [`is_structured`](https://json.nlohmann.me/api/basic_json/is_structured/index.md) - true for objects and arrays
- [Converting values](https://json.nlohmann.me/features/conversions/index.md) - convert JSON values to and from C++ types
- [Creating JSON values](https://json.nlohmann.me/features/creating_values/index.md) - build JSON values
+112 -3
View File
@@ -27,7 +27,77 @@ JSON defines the syntax of numbers as follows:
The following railroad diagram from [json.org](https://json.org) visualizes the number syntax:
![Syntax for JSON numbers](../../images/json_syntax_number.png)
<div class="railroad-wrap" markdown>
<svg class="railroad" viewBox="0 0 860 214" role="img" aria-labelledby="rr-title" xmlns="http://www.w3.org/2000/svg">
<title id="rr-title">Railroad diagram of the J&#8203;SON number syntax: optional minus, then 0 or a digit from 1 to 9 followed by digits, then an optional fraction (a dot and digits) and an optional exponent (e or E, an optional sign, and digits).</title>
<g class="rr-track" fill="none" stroke="currentColor" stroke-opacity=".6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M8 44 L850 44"/>
<path d="M24 44 L31 44 Q38 44 38 51 L38 82 Q38 92 48 92 L59 92"/>
<path d="M85 92 L96 92 Q106 92 106 82 L106 51 Q106 44 113 44 L120 44"/>
<path d="M120 44 L127 44 Q134 44 134 51 L134 82 Q134 92 144 92 L160 92"/>
<path d="M242 92 L370 92 Q380 92 380 82 L380 52 Q380 44 388 44 L396 44"/>
<path d="M242 92 L250 92 Q258 92 258 100 L258 126 Q258 136 268 136 L278 136"/>
<path d="M332 136 L340 136 Q348 136 348 128 L348 92"/>
<path d="M340 136 L340 160 Q340 170 330 170 L280 170 Q270 170 270 160 L270 136"/>
<path d="M396 44 L403 44 Q410 44 410 51 L410 84.5 Q410 92 417.5 92 L425 92"/>
<path d="M451 92 L462 92"/>
<path d="M524 92 L524 116 Q524 126 514 126 L466 126 Q456 126 456 116 L456 92"/>
<path d="M516 92 L523 92 Q530 92 530 85 L530 52 Q530 44 538 44 L546 44"/>
<path d="M546 44 L553 44 Q560 44 560 51 L560 83.5 Q560 92 568.5 92 L577 92"/>
<path d="M546 44 L553 44 Q560 44 560 51 L560 127.5 Q560 136 568.5 136 L577 136"/>
<path d="M603 92 L728 92"/>
<path d="M603 136 L611.5 136 Q620 136 620 127.5 L620 92"/>
<path d="M640 92 L647 92 Q654 92 654 99 L654 128 Q654 136 662 136 L670 136"/>
<path d="M640 92 L647 92 Q654 92 654 99 L654 172 Q654 180 662 180 L670 180"/>
<path d="M696 136 L704 136 Q712 136 712 128 L712 92"/>
<path d="M696 180 L704 180 Q712 180 712 172 L712 92"/>
<path d="M728 92 L746 92"/>
<path d="M808 92 L808 116 Q808 126 798 126 L748 126 Q738 126 738 116 L738 92"/>
<path d="M800 92 L808 92 Q816 92 816 84 L816 52 Q816 44 824 44 L832 44"/>
</g>
<polygon class="rr-arrow" points="2,38 12,44 2,50"/>
<polygon class="rr-arrow" points="846,38 858,44 846,50"/>
<circle class="rr-bg" cx="72" cy="92" r="13"/>
<circle class="rr-t" cx="72" cy="92" r="13"/>
<circle class="rr-bg" cx="257" cy="44" r="13"/>
<circle class="rr-t" cx="257" cy="44" r="13"/>
<rect class="rr-bg" x="160" y="78" width="82" height="28" rx="6"/>
<rect class="rr-n" x="160" y="78" width="82" height="28" rx="6"/>
<rect class="rr-bg" x="278" y="122" width="54" height="28" rx="6"/>
<rect class="rr-n" x="278" y="122" width="54" height="28" rx="6"/>
<circle class="rr-bg" cx="438" cy="92" r="13"/>
<circle class="rr-t" cx="438" cy="92" r="13"/>
<rect class="rr-bg" x="462" y="78" width="54" height="28" rx="6"/>
<rect class="rr-n" x="462" y="78" width="54" height="28" rx="6"/>
<circle class="rr-bg" cx="590" cy="92" r="13"/>
<circle class="rr-t" cx="590" cy="92" r="13"/>
<circle class="rr-bg" cx="590" cy="136" r="13"/>
<circle class="rr-t" cx="590" cy="136" r="13"/>
<circle class="rr-bg" cx="683" cy="136" r="13"/>
<circle class="rr-t" cx="683" cy="136" r="13"/>
<circle class="rr-bg" cx="683" cy="180" r="13"/>
<circle class="rr-t" cx="683" cy="180" r="13"/>
<rect class="rr-bg" x="746" y="78" width="54" height="28" rx="6"/>
<rect class="rr-n" x="746" y="78" width="54" height="28" rx="6"/>
<text class="rr-c" x="72" y="97">&#8722;</text>
<text class="rr-c" x="257" y="49">0</text>
<text class="rr-b" x="201" y="97">digit 1&#8211;9</text>
<text class="rr-b" x="305" y="141">digit</text>
<text class="rr-c" x="438" y="97">.</text>
<text class="rr-b" x="489" y="97">digit</text>
<text class="rr-c" x="590" y="97">e</text>
<text class="rr-c" x="590" y="141">E</text>
<text class="rr-c" x="683" y="141">&#8722;</text>
<text class="rr-c" x="683" y="185">+</text>
<text class="rr-b" x="773" y="97">digit</text>
<text class="rr-l rr-name" x="24" y="32">number</text>
<text class="rr-l" x="420" y="32">fraction</text>
<text class="rr-l" x="580" y="32">exponent</text>
</svg>
</div>
<p class="nj-caption" markdown>Read the diagram from left to right: every path along the lines spells a valid number, made of an optional minus sign, an integer part, an optional fraction, and an optional exponent.</p>
### Number interoperability
@@ -69,15 +139,17 @@ otherwise, it uses unsigned integer storage.
```mermaid
flowchart TD
A["number literal"] --> B{"has a fraction (.) or exponent (e/E)?"}
A["number literal"] --> B{{"has a fraction (.) or exponent (e/E)?"}}
B -->|"yes"| F["number_float_t"]
B -->|"no"| C{"has a leading minus sign?"}
B -->|"no"| C{{"has a leading minus sign?"}}
C -->|"yes"| D["try number_integer_t"]
C -->|"no"| E["try number_unsigned_t"]
D -->|"overflow"| F
E -->|"overflow"| F
```
<p class="nj-caption" markdown>How the parser picks the storage type of a number literal: a fraction or exponent always gives `number_float_t`; otherwise the sign selects the signed or unsigned integer type, and a value that overflows it is stored as `number_float_t`.</p>
!!! info "Notes"
- Numbers with a decimal digit or scientific notation are always stored as `#!c double`.
@@ -131,6 +203,32 @@ The JSON number grammar allows for different ways to express zero, and this libr
That is, `-0` is stored as a signed integer, but the serialization does not reproduce the `-`.
The literals mentioned on this page, parsed with `json::parse` and serialized with `dump()` (checked against the
library; pick one or type it to see the row):
<div class="nj-charts-num" markdown>
| Literal | Stored as (`type()`) | `dump()` |
|---------|----------------------|----------|
| `0` | `number_unsigned` (`std::uint64_t`) | `0` |
| `-0` | `number_integer` (`std::int64_t`) | `0` |
| `-0.0` | `number_float` (`double`) | `-0.0` |
| `1E3` | `number_float` (`double`) | `1000.0` |
| `-12345678912345789123456789` | `number_float` (`double`) | `-1.2345678912345788e+25` |
| `18446744073709551615` | `number_unsigned` (`std::uint64_t`) | `18446744073709551615` |
| `18446744073709551616` | `number_float` (`double`) | `1.8446744073709552e+19` |
| `-9223372036854775808` | `number_integer` (`std::int64_t`) | `-9223372036854775808` |
| `1E400` | exception `out_of_range.406` | (nothing, parsing fails) |
| `1E-400` | `number_float` (`double`) | `0.0` |
| `3.141592653589793238462643383279` | `number_float` (`double`) | `3.141592653589793` |
| `2555.5599999999999` | `number_float` (`double`) | `2555.56` |
| `0.0000972439793401814` | `number_float` (`double`) | `9.72439793401814e-05` |
| `12345E-5` | `number_float` (`double`) | `0.12345` |
</div>
<p class="nj-caption" markdown>Each row shows how a literal is stored and how `dump()` writes it back. The explorer only knows the literals in this list; other input is reported as not in the verified list.</p>
### Number serialization
- Integer numbers are serialized as is; that is, no scientific notation is used.
@@ -329,6 +427,8 @@ the stored number:
| [`type_name()`](../../api/basic_json/type_name.md) | `#!c "number"` | `#!c "number"` | `#!c "number"` | `#!c "string"` |
| [`type()`](../../api/basic_json/type.md) | `number_unsigned` | `number_integer` | `number_float` | `string` |
<p class="nj-table-caption" markdown>Return value of each function for a value that stores an unsigned integer, a signed integer, or a floating-point number, and for a string for comparison.</p>
### Template number types
The number types can be changed with template parameters.
@@ -362,3 +462,12 @@ The number types can be changed with template parameters.
Note values should then be parsed with `json_ld::parse` rather than `json::parse` as the latter would parse
floating-point values to `#!c double` before then converting them to `#!c long double`.
## See also
- [Types](index.md) - how all value types are stored
- [Converting values](../conversions.md) - convert numbers to C++ types
- [`number_integer_t`](../../api/basic_json/number_integer_t.md) - the signed integer type
- [`number_unsigned_t`](../../api/basic_json/number_unsigned_t.md) - the unsigned integer type
- [`number_float_t`](../../api/basic_json/number_float_t.md) - the floating-point type
- [`is_number`](../../api/basic_json/is_number.md) - check for a number of any kind
+6 -6
View File
@@ -1,11 +1,11 @@
<!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
A["number literal"] --&gt; B{"has a fraction (.) or exponent (e/E)?"}
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content="JSON for Modern C++ is a header-only C++11 library that makes JSON a first-class data type."><meta name=author content="Niels Lohmann"><link href="https://json.nlohmann.me/features/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=../../../css/custom.css><link rel=stylesheet href=../../../css/brand.css><link rel=stylesheet href=../../../css/fig-sax.css><link rel=stylesheet href=../../../css/fig-jsonview.css><link rel=stylesheet href=../../../css/fig-exceptions.css><link rel=stylesheet href=../../../css/fig-pointer.css><link rel=stylesheet href=../../../css/fig-charts.css><link rel=stylesheet href=../../../css/fig-integration.css><link rel=stylesheet href=../../../css/fig-macros.css><script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script></head> <body dir=ltr data-md-color-scheme=default data-md-color-primary=custom data-md-color-accent=custom> <input class=md-toggle data-md-toggle=drawer type=checkbox id=__drawer autocomplete=off> <input class=md-toggle data-md-toggle=search type=checkbox id=__search autocomplete=off> <label class=md-overlay for=__drawer></label> <div data-md-component=skip> <a href=#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> <img src=../../../images/wordmark-header.svg alt=logo> </a> <label class="md-header__button md-icon" for=__drawer> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg> </label> <div class=md-header__title data-md-component=header-title> <div class=md-header__ellipsis> <div class=md-header__topic> <span class=md-ellipsis> JSON for Modern C++ </span> </div> <div class=md-header__topic data-md-component=header-topic> <span class=md-ellipsis> 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=custom data-md-color-accent=custom aria-label="Switch to dark mode" type=radio name=__palette id=__palette_0> <label class="md-header__button md-icon" title="Switch to dark mode" for=__palette_1 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> <input class=md-option data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme=slate data-md-color-primary=custom data-md-color-accent=custom aria-label="Switch to light mode" type=radio name=__palette id=__palette_1> <label class="md-header__button md-icon" title="Switch to light mode" for=__palette_0 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> </form> <script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script> <label class="md-header__button md-icon" for=__search> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M9.5Line truncated
A["number literal"] --&gt; B{{"has a fraction (.) or exponent (e/E)?"}}
B --&gt;|"yes"| F["number_float_t"]
B --&gt;|"no"| C{"has a leading minus sign?"}
B --&gt;|"no"| C{{"has a leading minus sign?"}}
C --&gt;|"yes"| D["try number_integer_t"]
C --&gt;|"no"| E["try number_unsigned_t"]
D --&gt;|"overflow"| F
E --&gt;|"overflow"| F</code></pre> <div class="admonition info"> <p class=admonition-title>Notes</p> <ul> <li>Numbers with a decimal digit or scientific notation are always stored as <code class=highlight><span class=kt>double</span></code>.</li> <li>The number types can be changed, see <a href=#template-number-types>Template number types</a>. </li> <li>The library converts integers and floating-point numbers itself, independent of the locale. Floating-point numbers are correctly rounded (to nearest, ties to even). Only a <code class=highlight><span class=kt>long</span><span class=w> </span><span class=kt>double</span></code> that is not <abbr title="Institute of Electrical and Electronics Engineers">IEEE</abbr> 754 binary64 (e.g., the 80-bit x87 format) is converted with <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>from_chars</span></code> where available, or else with <a href="https://en.cppreference.com/w/cpp/string/byte/strtof"><code>std::strtold</code></a>. For that call, the library temporarily replaces the <code>.</code> with the decimal point of the current locale (which may be longer than one byte, e.g., in <code>fa_IR.UTF-8</code>), so the result does not depend on the locale either. Changing the locale in another thread during parsing is undefined behavior of the C library, though. Before version 3.13.0 <span class=unreleased-version title="Not part of a release yet; the latest release is 3.12.0.">unreleased</span>, the conversion was realized by <a href="https://en.cppreference.com/w/cpp/string/byte/strtoul"><code>std::strtoull</code></a>, <a href="https://en.cppreference.com/w/cpp/string/byte/strtol"><code>std::strtoll</code></a>, and <code>std::strtod</code>, respectively.</li> </ul> </div> <div class="admonition example"> <p class=admonition-title>Examples</p> <ul> <li>Integer <code class=highlight><span class=mi>-12345678912345789123456789</span></code> is smaller than <code class=highlight><span class=n>INT64_MIN</span></code> and will be stored as floating-point number <code class=highlight><span class=mf>-1.2345678912345788e+25</span></code>.</li> <li>Integer <code class=highlight><span class=mf>1E3</span></code> will be stored as floating-point number <code class=highlight><span class=mf>1000.0</span></code>.</li> </ul> </div> <h3 id=number-limits>Number limits<a class=headerlink href=#number-limits title="Permanent link">&para;</a></h3> <ul> <li>Any 64-bit signed or unsigned integer can be stored without loss of precision.</li> <li>Numbers exceeding the limits of <code class=highlight><span class=kt>double</span></code> (i.e., numbers whose rounded value is not satisfying <a href="https://en.cppreference.com/w/cpp/numeric/math/isfinite"><code>std::isfinite</code></a> such as <code class=highlight><span class=mf>1E400</span></code>) will throw exception <a href=../../../home/exceptions/#jsonexceptionout_of_range406><code>json.exception.out_of_range.406</code></a> during parsing. Numbers too small for <code class=highlight><span class=kt>double</span></code> (such as <code class=highlight><span class=mf>1E-400</span></code>) become zero, with the sign of the number.</li> <li>Floating-point numbers are rounded to the next number representable as <code>double</code>. For instance <code class=highlight><span class=mf>3.141592653589793238462643383279</span></code> is stored as <a href="https://float.exposed/0x400921fb54442d18"><code>0x400921fb54442d18</code></a>. This is the same behavior as the code <code class=highlight><span class=kt>double</span><span class=w> </span><span class=n>x</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=mf>3.141592653589793238462643383279</span><span class=p>;</span></code>.</li> </ul> <div class="admonition success"> <p class=admonition-title>Interoperability</p> <ul> <li>The library is interoperable with respect to the specification, because its supported range [-2<sup>63</sup>, 2<sup>64</sup>-1] is larger than the described range [-2<sup>53</sup>+1, 2<sup>53</sup>-1].</li> <li>All integers outside the range [-2<sup>63</sup>, 2<sup>64</sup>-1], as well as floating-point numbers are stored as <code>double</code>. This also concurs with the specification above.</li> </ul> </div> <h3 id=zeros>Zeros<a class=headerlink href=#zeros title="Permanent link">&para;</a></h3> <p>The <abbr title="JavaScript Object Notation">JSON</abbr> number grammar allows for different ways to express zero, and this library will store zeros differently:</p> <table> <thead> <tr> <th>Literal</th> <th>Stored value and type</th> <th>Serialization</th> </tr> </thead> <tbody> <tr> <td><code>0</code></td> <td><code class=highlight><span class=n>std</span><span class=o>::</span><span class=kt>uint64_t</span><span class=p>(</span><span class=mi>0</span><span class=p>)</span></code></td> <td><code>0</code></td> </tr> <tr> <td><code>-0</code></td> <td><code class=highlight><span class=n>std</span><span class=o>::</span>Line truncated
E --&gt;|"overflow"| F</code></pre> <p class=nj-caption>How the parser picks the storage type of a number literal: a fraction or exponent always gives <code>number_float_t</code>; otherwise the sign selects the signed or unsigned integer type, and a value that overflows it is stored as <code>number_float_t</code>.</p> <div class="admonition info"> <p class=admonition-title>Notes</p> <ul> <li>Numbers with a decimal digit or scientific notation are always stored as <code class=highlight><span class=kt>double</span></code>.</li> <li>The number types can be changed, see <a href=#template-number-types>Template number types</a>. </li> <li>The library converts integers and floating-point numbers itself, independent of the locale. Floating-point numbers are correctly rounded (to nearest, ties to even). Only a <code class=highlight><span class=kt>long</span><span class=w> </span><span class=kt>double</span></code> that is not <abbr title="Institute of Electrical and Electronics Engineers">IEEE</abbr> 754 binary64 (e.g., the 80-bit x87 format) is converted with <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>from_chars</span></code> where available, or else with <a href="https://en.cppreference.com/w/cpp/string/byte/strtof"><code>std::strtold</code></a>. For that call, the library temporarily replaces the <code>.</code> with the decimal point of the current locale (which may be longer than one byte, e.g., in <code>fa_IR.UTF-8</code>), so the result does not depend on the locale either. Changing the locale in another thread during parsing is undefined behavior of the C library, though. Before version 3.13.0 <span class=unreleased-version title="Not part of a release yet; the latest release is 3.12.0.">unreleased</span>, the conversion was realized by <a href="https://en.cppreference.com/w/cpp/string/byte/strtoul"><code>std::strtoull</code></a>, <a href="https://en.cppreference.com/w/cpp/string/byte/strtol"><code>std::strtoll</code></a>, and <code>std::strtod</code>, respectively.</li> </ul> </div> <div class="admonition example"> <p class=admonition-title>Examples</p> <ul> <li>Integer <code class=highlight><span class=mi>-12345678912345789123456789</span></code> is smaller than <code class=highlight><span class=n>INT64_MIN</span></code> and will be stored as floating-point number <code class=highlight><span class=mf>-1.2345678912345788e+25</span></code>.</li> <li>Integer <code class=highlight><span class=mf>1E3</span></code> will be stored as floating-point number <code class=highlight><span class=mf>1000.0</span></code>.</li> </ul> </div> <h3 id=number-limits>Number limits<a class=headerlink href=#number-limits title="Permanent link">&para;</a></h3> <ul> <li>Any 64-bit signed or unsigned integer can be stored without loss of precision.</li> <li>Numbers exceeding the limits of <code class=highlight><span class=kt>double</span></code> (i.e., numbers whose rounded value is not satisfying <a href="https://en.cppreference.com/w/cpp/numeric/math/isfinite"><code>std::isfinite</code></a> such as <code class=highlight><span class=mf>1E400</span></code>) will throw exception <a href=../../../home/exceptions/#jsonexceptionout_of_range406><code>json.exception.out_of_range.406</code></a> during parsing. Numbers too small for <code class=highlight><span class=kt>double</span></code> (such as <code class=highlight><span class=mf>1E-400</span></code>) become zero, with the sign of the number.</li> <li>Floating-point numbers are rounded to the next number representable as <code>double</code>. For instance <code class=highlight><span class=mf>3.141592653589793238462643383279</span></code> is stored as <a href="https://float.exposed/0x400921fb54442d18"><code>0x400921fb54442d18</code></a>. This is the same behavior as the code <code class=highlight><span class=kt>double</span><span class=w> </span><span class=n>x</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=mf>3.141592653589793238462643383279</span><span class=p>;</span></code>.</li> </ul> <div class="admonition success"> <p class=admonition-title>Interoperability</p> <ul> <li>The library is interoperable with respect to the specification, because its supported range [-2<sup>63</sup>, 2<sup>64</sup>-1] is larger than the described range [-2<sup>53</sup>+1, 2<sup>53</sup>-1].</li> <li>All integers outside the range [-2<sup>63</sup>, 2<sup>64</sup>-1], as well as floating-point numbers are stored as <code>double</code>. This also concurs with the specification above.</li> </ul> </div> <h3 id=zeros>Zeros<a class=headerlink href=#zeros title="Permanent link">&para;</a></h3> <p>The <abbr title="JavaScript Object Notation">JSON</abbr> number grammar allows for different ways to express zero, and this library will store zeros differently:</p> <table> <thead> <tr> <th>Literal</th> <th>Stored value and type</th> <th>Serialization</th> </tr> </thead> <tbody> <tr> <td><code>0</code></td> <td><code class=highlight><span Line 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>
@@ -59,5 +59,5 @@ val=nan
<span class=w> </span><span class=c1>// otherwise, take appropriate action</span>
<span class=w> </span><span class=c1>// ...</span>
<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></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="October 15, 2026 18:04:42 UTC">October 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 OFL 1.1Line truncated
</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> <p class=nj-table-caption>Return value of each function for a value that stores an unsigned integer, a signed integer, or a floating-point number, and for a string for comparison.</p> <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></Line 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> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li><a href=../ >Types</a> - how all value types are stored</li> <li><a href=../../conversions/ >Converting values</a> - convert numbers to C++ types</li> <li><a href=../../../api/basic_json/number_integer_t/ ><code>number_integer_t</code></a> - the signed integer type</li> <li><a href=../../../api/basic_json/number_unsigned_t/ ><code>number_unsigned_t</code></a> - the unsigned integer type</li> <li><a href=../../../api/basic_json/number_float_t/ ><code>number_float_t</code></a> - the floating-point type</li> <li><a href=../../../api/basic_json/is_number/ ><code>is_number</code></a> - check for a number of any kind</li> </ul> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="October 27, 2026 06:41:42 UTC">October 27, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <nav class="md-footer__inner md-grid" aria-label=Footer> <a href=../ class="md-footer__link md-footer__link--prev" aria-label="Previous: Types"> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg> </div> <div class=md-footer__title> <span class=md-footer__direction> Previous </span> <div class=md-ellipsis> Types </div> </div> </a> <a href=../template_parameters/ class="md-footer__link md-footer__link--next" aria-label="Next: Template Parameter Requirements"> <div class=md-footer__title> <span class=md-footer__direction> Next </span> <div class=md-ellipsis> Template Parameter Requirements </div> </div> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11z"/></svg> </div> </a> </nav> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> <div class=md-copyright__highlight> Copyright &copy; 2013-2026 Niels Lohmann </div> </div> <div class=md-social> <a href="https://github.com/nlohmann" target="_blank" rel="noopener" title="github.com" class="md-social__link"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 512 512"><!-- Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 9Line truncated
+38 -2
View File
@@ -20,6 +20,8 @@ An exponent part begins with the letter E in uppercase or lowercase, which may b
The following railroad diagram from [json.org](https://json.org) visualizes the number syntax:
Read the diagram from left to right: every path along the lines spells a valid number, made of an optional minus sign, an integer part, an optional fraction, and an optional exponent.
### Number interoperability
On number interoperability, the following remarks are made:
@@ -42,15 +44,17 @@ Positive integers are stored as `std::uint64_t`, while negative integers are sto
```
flowchart TD
A["number literal"] --> B{"has a fraction (.) or exponent (e/E)?"}
A["number literal"] --> B{{"has a fraction (.) or exponent (e/E)?"}}
B -->|"yes"| F["number_float_t"]
B -->|"no"| C{"has a leading minus sign?"}
B -->|"no"| C{{"has a leading minus sign?"}}
C -->|"yes"| D["try number_integer_t"]
C -->|"no"| E["try number_unsigned_t"]
D -->|"overflow"| F
E -->|"overflow"| F
```
How the parser picks the storage type of a number literal: a fraction or exponent always gives `number_float_t`; otherwise the sign selects the signed or unsigned integer type, and a value that overflows it is stored as `number_float_t`.
Notes
- Numbers with a decimal digit or scientific notation are always stored as `double`.
@@ -88,6 +92,27 @@ The JSON number grammar allows for different ways to express zero, and this libr
That is, `-0` is stored as a signed integer, but the serialization does not reproduce the `-`.
The literals mentioned on this page, parsed with `json::parse` and serialized with `dump()` (checked against the library; pick one or type it to see the row):
| Literal | Stored as (`type()`) | `dump()` |
| ---------------------------------- | ----------------------------------- | ------------------------- |
| `0` | `number_unsigned` (`std::uint64_t`) | `0` |
| `-0` | `number_integer` (`std::int64_t`) | `0` |
| `-0.0` | `number_float` (`double`) | `-0.0` |
| `1E3` | `number_float` (`double`) | `1000.0` |
| `-12345678912345789123456789` | `number_float` (`double`) | `-1.2345678912345788e+25` |
| `18446744073709551615` | `number_unsigned` (`std::uint64_t`) | `18446744073709551615` |
| `18446744073709551616` | `number_float` (`double`) | `1.8446744073709552e+19` |
| `-9223372036854775808` | `number_integer` (`std::int64_t`) | `-9223372036854775808` |
| `1E400` | exception `out_of_range.406` | (nothing, parsing fails) |
| `1E-400` | `number_float` (`double`) | `0.0` |
| `3.141592653589793238462643383279` | `number_float` (`double`) | `3.141592653589793` |
| `2555.5599999999999` | `number_float` (`double`) | `2555.56` |
| `0.0000972439793401814` | `number_float` (`double`) | `9.72439793401814e-05` |
| `12345E-5` | `number_float` (`double`) | `0.12345` |
Each row shows how a literal is stored and how `dump()` writes it back. The explorer only knows the literals in this list; other input is reported as not in the verified list.
### Number serialization
- Integer numbers are serialized as is; that is, no scientific notation is used.
@@ -266,6 +291,8 @@ As the example in [Number conversion](#number-conversion) shows, there are diffe
| [`type_name()`](https://json.nlohmann.me/api/basic_json/type_name/index.md) | `"number"` | `"number"` | `"number"` | `"string"` |
| [`type()`](https://json.nlohmann.me/api/basic_json/type/index.md) | `number_unsigned` | `number_integer` | `number_float` | `string` |
Return value of each function for a value that stores an unsigned integer, a signed integer, or a floating-point number, and for a string for comparison.
### Template number types
The number types can be changed with template parameters.
@@ -293,3 +320,12 @@ using json_ld = nlohmann::json::with_float_t<long double>;
```
Note values should then be parsed with `json_ld::parse` rather than `json::parse` as the latter would parse floating-point values to `double` before then converting them to `long double`.
## See also
- [Types](https://json.nlohmann.me/features/types/index.md) - how all value types are stored
- [Converting values](https://json.nlohmann.me/features/conversions/index.md) - convert numbers to C++ types
- [`number_integer_t`](https://json.nlohmann.me/api/basic_json/number_integer_t/index.md) - the signed integer type
- [`number_unsigned_t`](https://json.nlohmann.me/api/basic_json/number_unsigned_t/index.md) - the unsigned integer type
- [`number_float_t`](https://json.nlohmann.me/api/basic_json/number_float_t/index.md) - the floating-point type
- [`is_number`](https://json.nlohmann.me/api/basic_json/is_number/index.md) - check for a number of any kind
+39 -31
View File
@@ -1,7 +1,7 @@
# 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
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
@@ -16,9 +16,9 @@ To change a single template parameter and keep the others, use the member alias
Requirements are split into two groups:
- **Always required** -- needed to instantiate `basic_json` at all, or needed by functions that virtually every program
- **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
- **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.
@@ -56,8 +56,8 @@ Requirements are split into two groups:
!!! 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
`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
@@ -65,7 +65,7 @@ Requirements are split into two groups:
`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
`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.
@@ -93,7 +93,7 @@ i.e., the template arguments follow the order and meaning of `std::map`.
- 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).
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.
@@ -116,7 +116,7 @@ i.e., the template arguments follow the order and meaning of `std::map`.
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
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
@@ -200,7 +200,7 @@ object keys are serialized by [`dump`](../../api/basic_json/dump.md) and visited
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.
conservatively — this is correct, but slower.
#### Key order and duplicate keys
@@ -211,7 +211,7 @@ The library does not sort or de-duplicate keys itself; the behavior described in
`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
[`default_object_comparator_t`](../../api/basic_json/default_object_comparator_t.md) — a good starting point for
a custom `ObjectType`.
```cpp
@@ -485,7 +485,7 @@ using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
!!! 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`.
requirement above — a good starting point for a custom `ArrayType`.
```cpp
#pragma once
@@ -736,13 +736,13 @@ using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
### Required for JSON Pointer, `flatten`, and `diff`
- A static member `npos` and the member function `find_first_of(char, size_type)` -- together with `data()`,
- 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()`.
- `resize(n)` (one argument) -- used by `to_string` to size the result before the reference tokens are copied into it.
- `begin()` and `end()` -- used by
- `resize(n)` (one argument) — used by `to_string` to size the result before the reference tokens are copied into it.
- `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.
@@ -768,7 +768,7 @@ using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
| `#!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` |
| `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
@@ -786,13 +786,13 @@ using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
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
- 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
- **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.
@@ -803,7 +803,7 @@ using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
!!! 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
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.
@@ -1005,8 +1005,8 @@ using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
- 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
- **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
@@ -1017,7 +1017,7 @@ 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
`#!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
@@ -1031,7 +1031,7 @@ Both types are stored **directly** inside `basic_json`'s union.
- `#!cpp std::is_integral` must be satisfied: `NumberIntegerType` must be a **signed** integer type,
`NumberUnsignedType` an **unsigned** integer type or the same type as `NumberIntegerType` (see
[below](#same-type-for-both)). Class types are not supported -- among others, the constructors taking integer values
[below](#same-type-for-both)). 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.
@@ -1161,7 +1161,7 @@ process deeply nested values without recursion.
### Always required
- The template must accept **two** type arguments. It does not have to give the second one a default -- `basic_json`
- 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.
@@ -1194,7 +1194,7 @@ 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
- 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
@@ -1221,7 +1221,7 @@ 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`.
every requirement above — a good starting point for a custom `BinaryType`.
```cpp
#pragma once
@@ -1386,7 +1386,7 @@ such a container to a `basic_json` value.
| `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 |
| containers whose `value_type` is wider than one byte | see above — accepted by the compiler, wrong at runtime |
## `CustomBaseClass`
@@ -1433,7 +1433,15 @@ See [issue #3425](https://github.com/nlohmann/json/issues/3425), [`string_t`](..
## 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
- [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
- [`object_t`](../../api/basic_json/object_t.md) - the `ObjectType` in use
- [`array_t`](../../api/basic_json/array_t.md) - the `ArrayType` in use
- [`string_t`](../../api/basic_json/string_t.md) - the `StringType` in use
- [`json_serializer`](../../api/basic_json/json_serializer.md) - the `JSONSerializer` in use
- [`json_base_class_t`](../../api/basic_json/json_base_class_t.md) - the `CustomBaseClass` in use
- [`with_t`](../../api/basic_json/with_t.md) - derive a specialization with one parameter replaced
- [`get_allocator`](../../api/basic_json/get_allocator.md) - the allocator in use
@@ -1,9 +1,9 @@
<!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=../../json_view/ 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.5 6.5 Line truncated
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content="JSON for Modern C++ is a header-only C++11 library that makes JSON a first-class data type."><meta name=author content="Niels Lohmann"><link href="https://json.nlohmann.me/features/types/template_parameters/" rel="canonical"><link href=../number_handling/ rel=prev><link href=../../json_view/ 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=../../../css/custom.css><link rel=stylesheet href=../../../css/brand.css><link rel=stylesheet href=../../../css/fig-sax.css><link rel=stylesheet href=../../../css/fig-jsonview.css><link rel=stylesheet href=../../../css/fig-exceptions.css><link rel=stylesheet href=../../../css/fig-pointer.css><link rel=stylesheet href=../../../css/fig-charts.css><link rel=stylesheet href=../../../css/fig-integration.css><link rel=stylesheet href=../../../css/fig-macros.css><script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script></head> <body dir=ltr data-md-color-scheme=default data-md-color-primary=custom data-md-color-accent=custom> <input class=md-toggle data-md-toggle=drawer type=checkbox id=__drawer autocomplete=off> <input class=md-toggle data-md-toggle=search type=checkbox id=__search autocomplete=off> <label class=md-overlay for=__drawer></label> <div data-md-component=skip> <a href=#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> <img src=../../../images/wordmark-header.svg alt=logo> </a> <label class="md-header__button md-icon" for=__drawer> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg> </label> <div class=md-header__title data-md-component=header-title> <div class=md-header__ellipsis> <div class=md-header__topic> <span class=md-ellipsis> JSON for Modern C++ </span> </div> <div class=md-header__topic data-md-component=header-topic> <span class=md-ellipsis> 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=custom data-md-color-accent=custom aria-label="Switch to dark mode" type=radio name=__palette id=__palette_0> <label class="md-header__button md-icon" title="Switch to dark mode" for=__palette_1 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> <input class=md-option data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme=slate data-md-color-primary=custom data-md-color-accent=custom aria-label="Switch to light mode" type=radio name=__palette id=__palette_1> <label class="md-header__button md-icon" title="Switch to light mode" for=__palette_0 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> </form> <script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script> <label class="md-header__button md-icon" for=__search> <svg xmlnsLine 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
</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> siLine 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>
@@ -21,7 +21,7 @@
<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>json</span><span class=o>::</span><span class=n>with_object_t</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>
</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>
@@ -202,7 +202,7 @@
<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>
</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>
@@ -374,7 +374,7 @@
<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 passes <code>data()</code> to functions that take a <code class=highlight><span class=k>const</span><span class=w> </span><span class=kt>char</span><span class=o>*</span></code>, such as <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>strtold</span></code> (only used to parse a <code class=highlight><span class=kt>long</span><span class=w> </span><span class=kt>double</span></code> that is not <abbr title="Institute of Electrical and Electronics Engineers">IEEE</abbr> 754 binary64, see <a href=#numberfloattype><code>NumberFloatType</code></a>). <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 Line truncated
</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 passes <code>data()</code> to functions that take a <code class=highlight><span class=k>const</span><span class=w> </span><span class=kt>char</span><span class=o>*</span></code>, such as <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>strtold</span></code> (only used to parse a <code class=highlight><span class=kt>long</span><span class=w> </span><span class=kt>double</span></code> that is not <abbr title="Institute of Electrical and Electronics Engineers">IEEE</abbr> 754 binary64, see <a href=#numberfloattype><code>NumberFloatType</code></a>). <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 Line truncated
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;cstddef&gt;</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;ostream&gt;</span>
@@ -548,8 +548,8 @@
<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 or the same type as <code>NumberIntegerType</code> (see <a href=#same-type-for-both>below</a>). 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>An unsigned <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>stLine 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. <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>
</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 or the same type as <code>NumberIntegerType</code> (see <a href=#same-type-for-both>below</a>). 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>An unsigned <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 classLine 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. <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>
@@ -678,4 +678,4 @@
<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
</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> </trLine truncated
+43 -36
View File
@@ -1,6 +1,6 @@
# Template Parameter Requirements
Class [`basic_json`](https://json.nlohmann.me/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`](https://json.nlohmann.me/api/basic_json/object_t/index.md), [`array_t`](https://json.nlohmann.me/api/basic_json/array_t/index.md), [`string_t`](https://json.nlohmann.me/api/basic_json/string_t/index.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.
Class [`basic_json`](https://json.nlohmann.me/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`](https://json.nlohmann.me/api/basic_json/object_t/index.md), [`array_t`](https://json.nlohmann.me/api/basic_json/array_t/index.md), [`string_t`](https://json.nlohmann.me/api/basic_json/string_t/index.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.
To change a single template parameter and keep the others, use the member alias templates [`with_*_t`](https://json.nlohmann.me/api/basic_json/with_t/index.md); for instance, `nlohmann::json::with_float_t<long double>` is `json` with `long double` as [`number_float_t`](https://json.nlohmann.me/api/basic_json/number_float_t/index.md).
@@ -8,8 +8,8 @@ To change a single template parameter and keep the others, use the member alias
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`](https://json.nlohmann.me/api/basic_json/dump/index.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.
- **Always required** — needed to instantiate `basic_json` at all, or needed by functions that virtually every program uses (construction, element access, [`dump`](https://json.nlohmann.me/api/basic_json/dump/index.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.
Requirements are not checked
@@ -37,9 +37,9 @@ Three requirements are checked with a `static_assert`: the array iterator catego
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`](https://json.nlohmann.me/api/basic_json/object_comparator_t/index.md) -- i.e. while `basic_json` is still an incomplete type. `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 `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`.
`object_t` is instantiated inside the definition of `basic_json` — it is probed for a `key_compare` member to form [`object_comparator_t`](https://json.nlohmann.me/api/basic_json/object_comparator_t/index.md) — i.e. while `basic_json` is still an incomplete type. `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 `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 `std::is_trivially_move_assignable<basic_json>` it evaluates while instantiating itself re-enters the library's own trait machinery mid-instantiation.
`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 `std::is_trivially_move_assignable<basic_json>` it evaluates while instantiating itself re-enters the library's own trait machinery mid-instantiation.
Folly requires C++20
@@ -61,7 +61,7 @@ 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).
- 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`](https://json.nlohmann.me/api/basic_json/object_comparator_t/index.md); otherwise [`default_object_comparator_t`](https://json.nlohmann.me/api/basic_json/default_object_comparator_t/index.md) is used.
- Member types `key_type`, `mapped_type`, `value_type`, and `iterator`.
- `value_type` must behave like `std::pair<const key_type, mapped_type>`; the library accesses `.first` and `.second` on it.
@@ -72,7 +72,7 @@ i.e., the template arguments follow the order and meaning of `std::map`.
- `at(key)` is required only by [`to_ubjson`](https://json.nlohmann.me/api/basic_json/to_ubjson/index.md) and [`to_bjdata`](https://json.nlohmann.me/api/basic_json/to_bjdata/index.md), but every container tried here provides it.
- `emplace` and `insert(value_type)` must return `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](https://json.nlohmann.me/api/basic_json/operator_eq/index.md).
- 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](https://json.nlohmann.me/api/basic_json/operator_eq/index.md).
### Required for heterogeneous key lookup
@@ -132,7 +132,7 @@ The library never relies on the container's iteration order for correctness; it
#### `capacity()` marks a container as insertion-ordered
With [`JSON_DIAGNOSTICS`](https://json.nlohmann.me/api/macros/json_diagnostics/index.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.
With [`JSON_DIAGNOSTICS`](https://json.nlohmann.me/api/macros/json_diagnostics/index.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
@@ -140,7 +140,7 @@ The library does not sort or de-duplicate keys itself; the behavior described in
Reference implementation
`docs/mkdocs/docs/examples/custom_object_type.hpp` wraps a private `std::map` and satisfies every requirement above. It does not define `key_compare`, so `object_comparator_t` falls back to [`default_object_comparator_t`](https://json.nlohmann.me/api/basic_json/default_object_comparator_t/index.md) -- a good starting point for a custom `ObjectType`.
`docs/mkdocs/docs/examples/custom_object_type.hpp` wraps a private `std::map` and satisfies every requirement above. It does not define `key_compare`, so `object_comparator_t` falls back to [`default_object_comparator_t`](https://json.nlohmann.me/api/basic_json/default_object_comparator_t/index.md) — a good starting point for a custom `ObjectType`.
```
#pragma once
@@ -393,7 +393,7 @@ With [`JSON_DIAGNOSTICS`](https://json.nlohmann.me/api/macros/json_diagnostics/i
Reference implementation
`docs/mkdocs/docs/examples/custom_array_type.hpp` wraps a private `std::vector` and satisfies every requirement above -- a good starting point for a custom `ArrayType`.
`docs/mkdocs/docs/examples/custom_array_type.hpp` wraps a private `std::vector` and satisfies every requirement above — a good starting point for a custom `ArrayType`.
```
#pragma once
@@ -622,10 +622,10 @@ true
### 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.
- 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()`.
- `resize(n)` (one argument) -- used by `to_string` to size the result before the reference tokens are copied into it.
- `begin()` and `end()` -- used by [`operator[](const json_pointer&)`](https://json.nlohmann.me/api/basic_json/operator%5B%5D/index.md) to decide whether a reference token denotes an array index.
- `resize(n)` (one argument) — used by `to_string` to size the result before the reference tokens are copied into it.
- `begin()` and `end()` — used by [`operator[](const json_pointer&)`](https://json.nlohmann.me/api/basic_json/operator%5B%5D/index.md) to decide whether a reference token denotes an array index.
### Required for other functionality
@@ -642,15 +642,15 @@ true
### Compatible types
| Type | Notes |
| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `std::string` (default) | |
| `std::basic_string` with a custom **stateless** allocator | |
| `std::pmr::string` | see the warning below before relying on the memory resource |
| `boost::container::string` | needs a user-supplied `std::hash` specialization (Boost provides `boost::hash` instead) |
| `folly::fbstring` | requires C++20, see the note above |
| `eastl::string` | needs a user-supplied `std::hash` and an ADL `int_to_string` (it is not assignable from a `std::string`); [`parse`](https://json.nlohmann.me/api/basic_json/parse/index.md) does not accept it directly -- pass a character range or a `std::string` |
| a custom string class in a user-defined namespace | if the requirements above are met |
| Type | Notes |
| --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `std::string` (default) | |
| `std::basic_string` with a custom **stateless** allocator | |
| `std::pmr::string` | see the warning below before relying on the memory resource |
| `boost::container::string` | needs a user-supplied `std::hash` specialization (Boost provides `boost::hash` instead) |
| `folly::fbstring` | requires C++20, see the note above |
| `eastl::string` | needs a user-supplied `std::hash` and an ADL `int_to_string` (it is not assignable from a `std::string`); [`parse`](https://json.nlohmann.me/api/basic_json/parse/index.md) does not accept it directly — pass a character range or a `std::string` |
| a custom string class in a user-defined namespace | if the requirements above are met |
### Types that cannot be used
@@ -665,16 +665,16 @@ 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`](https://json.nlohmann.me/api/basic_json/parse/index.md), from [`dump`](https://json.nlohmann.me/api/basic_json/dump/index.md), or by default construction -- allocates from `std::pmr::get_default_resource()`.
- Every string the library itself produces — from [`parse`](https://json.nlohmann.me/api/basic_json/parse/index.md), from [`dump`](https://json.nlohmann.me/api/basic_json/dump/index.md), or by default construction — allocates from `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 `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`.
- **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 `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 `std::pmr::set_default_resource()`.
Reference implementation
`docs/mkdocs/docs/examples/custom_string_type.hpp` wraps a private `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.
`docs/mkdocs/docs/examples/custom_string_type.hpp` wraps a private `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.
```
#pragma once
@@ -870,7 +870,7 @@ true
### 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 `bool` -- an `explicit` constructor is not enough, because the `to_json` overload for a custom `BooleanType` is constrained on `std::is_convertible` -- and contextually convertible to `bool` (here an `explicit operator bool` is fine).
- **Implicitly** convertible from `bool` — an `explicit` constructor is not enough, because the `to_json` overload for a custom `BooleanType` is constrained on `std::is_convertible` — and contextually convertible to `bool` (here an `explicit operator bool` is fine).
- Comparison operators `==`, `!=`, `<`, `<=`, `>`, `>=` (or `<=>`).
- Convertible from and to `bool` through the serializer, because [`get<bool>()`](https://json.nlohmann.me/api/basic_json/get/index.md) is used internally.
@@ -878,7 +878,7 @@ There is little reason to use anything other than `bool` here.
### Compatible types
`bool` is the only usable choice. Another trivially copyable type that is implicitly convertible to and from `bool` -- `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 `std::uint8_t` at all (the boolean and unsigned-integer `to_json` overloads become ambiguous), and [`get<std::uint8_t>()`](https://json.nlohmann.me/api/basic_json/get/index.md) on a number throws [`type_error.302`](https://json.nlohmann.me/home/exceptions/#jsonexceptiontype_error302) instead of returning the value.
`bool` is the only usable choice. Another trivially copyable type that is implicitly convertible to and from `bool` — `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 `std::uint8_t` at all (the boolean and unsigned-integer `to_json` overloads become ambiguous), and [`get<std::uint8_t>()`](https://json.nlohmann.me/api/basic_json/get/index.md) on a number throws [`type_error.302`](https://json.nlohmann.me/home/exceptions/#jsonexceptiontype_error302) instead of returning the value.
## `NumberIntegerType` and `NumberUnsignedType`
@@ -886,7 +886,7 @@ Both types are stored **directly** inside `basic_json`'s union.
### Always required
- `std::is_integral` must be satisfied: `NumberIntegerType` must be a **signed** integer type, `NumberUnsignedType` an **unsigned** integer type or the same type as `NumberIntegerType` (see [below](#same-type-for-both)). Class types are not supported -- among others, the constructors taking integer values are constrained on `std::is_integral`.
- `std::is_integral` must be satisfied: `NumberIntegerType` must be a **signed** integer type, `NumberUnsignedType` an **unsigned** integer type or the same type as `NumberIntegerType` (see [below](#same-type-for-both)). Class types are not supported — among others, the constructors taking integer values are constrained on `std::is_integral`.
- Trivially default-constructible, trivially copyable, and trivially destructible (union member).
- `std::numeric_limits` must be specialized for both types.
- An unsigned `NumberUnsignedType` must be able to represent the absolute value of every `NumberIntegerType` value; serialization of negative numbers converts the value to `NumberUnsignedType`. A `static_assert` requires it to be at least as wide as `NumberIntegerType`, which is what that amounts to for the standard integer types.
@@ -977,7 +977,7 @@ If `std::numeric_limits<NumberFloatType>` describes an IEEE 754 binary64 number,
### 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 `template<typename T, typename SFINAE = void> class JSONSerializer`, so uses such as `JSONSerializer<T>` inside the library supply `void` themselves. The second parameter exists so that partial specializations can be constrained by SFINAE.
- The template must accept **two** type arguments. It does not have to give the second one a default — `basic_json` declares the parameter as `template<typename T, typename SFINAE = void> class JSONSerializer`, so uses such as `JSONSerializer<T>` inside the library supply `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 `static void to_json(basic_json&, T)` must exist.
- For every type `T` that is converted **from** a JSON value, either `static void from_json(const basic_json&, T&)` or `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](https://json.nlohmann.me/features/arbitrary_types/index.md).
- To support the [converting constructor](https://json.nlohmann.me/api/basic_json/basic_json/index.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.
@@ -1000,7 +1000,7 @@ using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
### Always required
- A non-`final` class type -- [`byte_container_with_subtype`](https://json.nlohmann.me/api/byte_container_with_subtype/index.md) derives from it publicly.
- A non-`final` class type — [`byte_container_with_subtype`](https://json.nlohmann.me/api/byte_container_with_subtype/index.md) derives from it publicly.
- A member type `value_type` that is **exactly one byte** wide (e.g., `std::uint8_t`, `char`, or `std::byte`). Readers and writers reinterpret the container's storage as raw bytes, so a wider `value_type` is rejected with a `static_assert`.
- Contiguous storage: the binary readers `std::memcpy` into `&binary[n]`, the writers `reinterpret_cast` `data()`. `data() + n` would do for the readers too, but they share one helper with [`StringType`](#stringtype), whose non-`const` `data()` is C++17 and later only.
- Default-constructible, copy-constructible, and move-constructible.
@@ -1017,7 +1017,7 @@ See [`binary_t`](https://json.nlohmann.me/api/basic_json/binary_t/index.md) for
Reference implementation
`docs/mkdocs/docs/examples/custom_binary_type.hpp` wraps a private `std::vector<std::uint8_t>` and satisfies every requirement above -- a good starting point for a custom `BinaryType`.
`docs/mkdocs/docs/examples/custom_binary_type.hpp` wraps a private `std::vector<std::uint8_t>` and satisfies every requirement above — a good starting point for a custom `BinaryType`.
```
#pragma once
@@ -1179,7 +1179,7 @@ true
| `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 |
| `std::string` | `binary_t::container_type` and `string_t` would be the same type, so the two [`swap`](https://json.nlohmann.me/api/basic_json/swap/index.md) overloads collide and `basic_json` cannot be instantiated at all |
| `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 |
| containers whose `value_type` is wider than one byte | see above — accepted by the compiler, wrong at runtime |
## `CustomBaseClass`
@@ -1216,7 +1216,14 @@ See [issue #3425](https://github.com/nlohmann/json/issues/3425), [`string_t`](ht
## See also
- [Types](https://json.nlohmann.me/features/types/index.md) -- overview of how JSON values are stored
- [Number Handling](https://json.nlohmann.me/features/types/number_handling/index.md) -- how the number types affect parsing and serialization
- [Object Order](https://json.nlohmann.me/features/object_order/index.md) -- using an insertion-ordered `ObjectType`
- [`basic_json`](https://json.nlohmann.me/api/basic_json/index.md) -- API documentation of the class template
- [Types](https://json.nlohmann.me/features/types/index.md) - overview of how JSON values are stored
- [Number Handling](https://json.nlohmann.me/features/types/number_handling/index.md) - how the number types affect parsing and serialization
- [Object Order](https://json.nlohmann.me/features/object_order/index.md) - using an insertion-ordered `ObjectType`
- [`basic_json`](https://json.nlohmann.me/api/basic_json/index.md) - API documentation of the class template
- [`object_t`](https://json.nlohmann.me/api/basic_json/object_t/index.md) - the `ObjectType` in use
- [`array_t`](https://json.nlohmann.me/api/basic_json/array_t/index.md) - the `ArrayType` in use
- [`string_t`](https://json.nlohmann.me/api/basic_json/string_t/index.md) - the `StringType` in use
- [`json_serializer`](https://json.nlohmann.me/api/basic_json/json_serializer/index.md) - the `JSONSerializer` in use
- [`json_base_class_t`](https://json.nlohmann.me/api/basic_json/json_base_class_t/index.md) - the `CustomBaseClass` in use
- [`with_t`](https://json.nlohmann.me/api/basic_json/with_t/index.md) - derive a specialization with one parameter replaced
- [`get_allocator`](https://json.nlohmann.me/api/basic_json/get_allocator/index.md) - the allocator in use