deploy: 94fe31eb9b
This commit is contained in:
1 parent
41c601a7d1
commit
d2e264bd84
1400 files changed
+11859
-5440
No files matched your search
@@ -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/parsing/" rel="canonical"><link href=../performance/ rel=prev><link href=json_lines/ rel=next><link rel=icon href=../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>Parsing - 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=#parsing 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> Parsing </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-componeLine truncated
|
||||
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=author content="Niels Lohmann"><link href="https://json.nlohmann.me/features/parsing/" rel="canonical"><link href=../performance/ rel=prev><link href=json_lines/ rel=next><link rel=icon href=../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>Parsing - 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=#parsing 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> Parsing </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-componeLine truncated
|
||||
I["JSON input"] --> P["parse()"]
|
||||
I --> S["sax_parse()"]
|
||||
I --> A["accept()"]
|
||||
@@ -10,8 +10,8 @@
|
||||
<span class=c1>// parse from a file</span>
|
||||
<span class=n>std</span><span class=o>::</span><span class=n>ifstream</span><span class=w> </span><span class=n>f</span><span class=p>(</span><span class=s>"example.json"</span><span class=p>);</span>
|
||||
<span class=n>json</span><span class=w> </span><span class=n>data</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>parse</span><span class=p>(</span><span class=n>f</span><span class=p>);</span>
|
||||
</code></pre></div> <p>The input must be encoded in <abbr title="Unicode Transformation Format">UTF</abbr>-8; other encodings are not supported. The exception is wide-character input, which is read as <abbr title="Unicode Transformation Format">UTF</abbr>-16 or <abbr title="Unicode Transformation Format">UTF</abbr>-32 -- depending on the character type -- and converted to <abbr title="Unicode Transformation Format">UTF</abbr>-8; see the <a href=../../api/basic_json/parse/ ><code>parse</code></a> page for an example. A single input may contain only one <abbr title="JavaScript Object Notation">JSON</abbr> value. Inputs consisting of multiple values separated by newlines are handled by the <a href=json_lines/ ><abbr title="JavaScript Object Notation">JSON</abbr> Lines</a> format.</p> <p>By default, the library rejects comments and trailing commas. Both can be enabled with parameters of the <code>parse</code> function — see <a href=../comments/ >comments</a> and <a href=../trailing_commas/ >trailing commas</a>.</p> <p><a href=../../api/basic_json_document/parse/ ><code>basic_json_document::parse</code></a> accepts the same inputs with the same options, but keeps the result in a document rather than in a <code>basic_json</code> value; see <a href=#documents-and-views>Documents and views</a> below.</p> <h2 id=strictness-and-trailing-data>Strictness and trailing data<a class=headerlink href=#strictness-and-trailing-data title="Permanent link">¶</a></h2> <p><a href=../../api/basic_json/parse/ ><code>parse</code></a> reads a single <abbr title="JavaScript Object Notation">JSON</abbr> value and requires the whole input to be consumed: any non-whitespace data after the value is reported as a parse error. Use it when you want to guarantee that an input is exactly one complete <abbr title="JavaScript Object Notation">JSON</abbr> document.</p> <p><a href=../../api/operator_gtgt/ ><code>operator>></code></a> follows relaxed <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>istream</span></code> semantics instead: it parses one <abbr title="JavaScript Object Notation">JSON</abbr> value and leaves the stream positioned right after it, without requiring the rest of the stream to be consumed. This is what makes it possible to read several concatenated values from the same stream, but it also means that "a valid document followed by trailing bytes" is accepted rather than rejected. If you are validating conformance, or need to reject any input that is not exactly one <abbr title="JavaScript Object Notation">JSON</abbr> document, prefer <code>parse</code>.</p> <p>When using <code>operator>></code> to read several concatenated values this way, a value that is a number must be followed by whitespace, because <code>operator>></code> consumes the character that terminates a number, unless <a href=../../api/macros/json_precise_stream_position/ ><code>JSON_PRECISE_STREAM_POSITION</code></a> is defined to <code>1</code> — see the <a href=../../api/operator_gtgt/#notes><code>operator>></code> notes</a> for details and examples.</p> <h2 id=input-sources-and-performance>Input sources and performance<a class=headerlink href=#input-sources-and-performance title="Permanent link">¶</a></h2> <p>All inputs produce the same values and the same exceptions, but they are read in different ways, which makes some of them faster than others:</p> <table> <thead> <tr> <th>input</th> <th>how it is read</th> </tr> </thead> <tbody> <tr> <td>strings, string views, string literals, contiguous containers, pointer or iterator ranges over contiguous memory</td> <td>the whole input is scanned in bulk: runs of string characters, numbers, and indentation are recognized several bytes at a time</td> </tr> <tr> <td><code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>istream</span></code> (<code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>ifstream</span></code>, <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>istringstream</span></code>, ...)</td> <td>the characters the stream buffer holds are scanned in bulk like a string; the stream buffer is asked for more when they are used up</td> </tr> <tr> <td><code class=highlight><span class=kt>FILE</span><span class=o>*</span></code></td> <td>one character at a time, with the file locked once for the whole parse</td> </tr> <tr> <td>other iterator ranges (e.g., <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>list</span><span class=o><</span><span class=kt>char</span><span class=o>></span></code>, <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>istreambuf_iterator</span><span class=o><</span><span class=kt>char</span><span class=o>></span></code>), wide strings</td> <td>one character at a time</td> </tr> </tbody> </table> <p>Parsing a file from a <code class=highlight><span claLine truncated
|
||||
</code></pre></div> <p>The input must be encoded in <abbr title="Unicode Transformation Format">UTF</abbr>-8; other encodings are not supported. The exception is wide-character input, which is read as <abbr title="Unicode Transformation Format">UTF</abbr>-16 or <abbr title="Unicode Transformation Format">UTF</abbr>-32 -- depending on the character type -- and converted to <abbr title="Unicode Transformation Format">UTF</abbr>-8; see the <a href=../../api/basic_json/parse/ ><code>parse</code></a> page for an example. A single input may contain only one <abbr title="JavaScript Object Notation">JSON</abbr> value. Inputs consisting of multiple values separated by newlines are handled by the <a href=json_lines/ ><abbr title="JavaScript Object Notation">JSON</abbr> Lines</a> format; input that arrives in chunks or contains several values is covered in <a href=large_and_partial_input/ >Large, streamed, and partial input</a>.</p> <p>By default, the library rejects comments and trailing commas. Both can be enabled with parameters of the <code>parse</code> function — see <a href=../comments/ >comments</a> and <a href=../trailing_commas/ >trailing commas</a>.</p> <p><a href=../../api/basic_json_document/parse/ ><code>basic_json_document::parse</code></a> accepts the same inputs with the same options, but keeps the result in a document rather than in a <code>basic_json</code> value; see <a href=#documents-and-views>Documents and views</a> below.</p> <h2 id=strictness-and-trailing-data>Strictness and trailing data<a class=headerlink href=#strictness-and-trailing-data title="Permanent link">¶</a></h2> <p><a href=../../api/basic_json/parse/ ><code>parse</code></a> reads a single <abbr title="JavaScript Object Notation">JSON</abbr> value and requires the whole input to be consumed: any non-whitespace data after the value is reported as a parse error. Use it when you want to guarantee that an input is exactly one complete <abbr title="JavaScript Object Notation">JSON</abbr> document.</p> <p><a href=../../api/operator_gtgt/ ><code>operator>></code></a> follows relaxed <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>istream</span></code> semantics instead: it parses one <abbr title="JavaScript Object Notation">JSON</abbr> value and leaves the stream positioned right after it, without requiring the rest of the stream to be consumed. This is what makes it possible to read several concatenated values from the same stream, but it also means that "a valid document followed by trailing bytes" is accepted rather than rejected. If you are validating conformance, or need to reject any input that is not exactly one <abbr title="JavaScript Object Notation">JSON</abbr> document, prefer <code>parse</code>.</p> <p>When using <code>operator>></code> to read several concatenated values this way, a value that is a number must be followed by whitespace, because <code>operator>></code> consumes the character that terminates a number, unless <a href=../../api/macros/json_precise_stream_position/ ><code>JSON_PRECISE_STREAM_POSITION</code></a> is defined to <code>1</code> — see the <a href=../../api/operator_gtgt/#notes><code>operator>></code> notes</a> for details and examples.</p> <h2 id=input-sources-and-performance>Input sources and performance<a class=headerlink href=#input-sources-and-performance title="Permanent link">¶</a></h2> <p>All inputs produce the same values and the same exceptions, but they are read in different ways, which makes some of them faster than others:</p> <table> <thead> <tr> <th>input</th> <th>how it is read</th> </tr> </thead> <tbody> <tr> <td>strings, string views, string literals, contiguous containers, pointer or iterator ranges over contiguous memory</td> <td>the whole input is scanned in bulk: runs of string characters, numbers, and indentation are recognized several bytes at a time</td> </tr> <tr> <td><code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>istream</span></code> (<code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>ifstream</span></code>, <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>istringstream</span></code>, ...)</td> <td>the characters the stream buffer holds are scanned in bulk like a string; the stream buffer is asked for more when they are used up</td> </tr> <tr> <td><code class=highlight><span class=kt>FILE</span><span class=o>*</span></code></td> <td>one character at a time, with the file locked once for the whole parse</td> </tr> <tr> <td>other iterator ranges (e.g., <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>list</span><span class=o><</span><span class=kt>char</span><span class=o>></span></code>, <code class=highlight><span class=n>std</span><span class=o>::</span><span class=n>istreambuf_iterator</span><span class=o><</span><span class=kt>char</span><span class=o>></spLine truncated
|
||||
|
||||
<span class=n>json_document</span><span class=w> </span><span class=n>doc</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>json_document</span><span class=o>::</span><span class=n>parse</span><span class=p>(</span><span class=sa>R</span><span class=s>"</span><span class=dl>(</span><span class=s>{"happy": true, "pi": 3.141}</span><span class=dl>)</span><span class=s>"</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><<</span><span class=w> </span><span class=n>doc</span><span class=p>.</span><span class=n>root</span><span class=p>()[</span><span class=s>"happy"</span><span class=p>].</span><span class=n>get</span><span class=o><</span><span class=kt>bool</span><span class=o>></span><span class=p>()</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
</code></pre></div> <p>See <a href=../json_view/ >Zero-copy <abbr title="JavaScript Object Notation">JSON</abbr> views</a> for the concept and the trade-offs.</p> <h2 id=exceptions>Exceptions<a class=headerlink href=#exceptions title="Permanent link">¶</a></h2> <p>When the input is not valid <abbr title="JavaScript Object Notation">JSON</abbr>, the <code>parse</code> function throws an exception by default. If exceptions are undesired or unavailable, the parser can instead return a discarded value, or <a href=../../api/basic_json/accept/ ><code>accept</code></a> can be used to only check whether an input is valid <abbr title="JavaScript Object Notation">JSON</abbr>. See <a href=parse_exceptions/ >parsing and exceptions</a> for the available options.</p> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">¶</a></h2> <ul> <li><a href=../../api/basic_json/parse/ ><code>parse</code></a> - deserialize from a compatible input</li> <li><a href=../../api/basic_json_document/parse/ ><code>basic_json_document::parse</code></a> - deserialize into a document instead of a value</li> <li><a href=../../api/basic_json/accept/ ><code>accept</code></a> - check if the input is valid <abbr title="JavaScript Object Notation">JSON</abbr></li> <li><a href=../../api/basic_json/sax_parse/ ><code>sax_parse</code></a> - generate <abbr title="Simple API for XML">SAX</abbr> events</li> <li><a href=json_lines/ ><abbr title="JavaScript Object Notation">JSON</abbr> Lines</a> - parse newline-delimited <abbr title="JavaScript Object Notation">JSON</abbr></li> <li><a href=parser_callbacks/ >parser callbacks</a> - influence the parsing by a callback function</li> <li><a href=sax_interface/ ><abbr title="Simple API for XML">SAX</abbr> interface</a> - implement a custom <abbr title="Simple API for XML">SAX</abbr> handler</li> <li><a href=parse_exceptions/ >parsing and exceptions</a> - control error handling</li> <li><a href=untrusted_input/ >parsing untrusted input</a> - what to consider when parsing input from untrusted sources</li> <li><a href=../json_view/ >Zero-copy <abbr title="JavaScript Object Notation">JSON</abbr> views</a> - parse into a document and read it through a view</li> </ul> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="October 25, 2026 05:18:07 UTC">October 25, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> <div class=md-copyright__highlight> Copyright © 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-2Line truncated
|
||||
</code></pre></div> <p>See <a href=../json_view/ >Zero-copy <abbr title="JavaScript Object Notation">JSON</abbr> views</a> for the concept and the trade-offs.</p> <h2 id=exceptions>Exceptions<a class=headerlink href=#exceptions title="Permanent link">¶</a></h2> <p>When the input is not valid <abbr title="JavaScript Object Notation">JSON</abbr>, the <code>parse</code> function throws an exception by default. If exceptions are undesired or unavailable, the parser can instead return a discarded value, or <a href=../../api/basic_json/accept/ ><code>accept</code></a> can be used to only check whether an input is valid <abbr title="JavaScript Object Notation">JSON</abbr>. See <a href=parse_exceptions/ >parsing and exceptions</a> for the available options.</p> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">¶</a></h2> <ul> <li><a href=../../api/basic_json/parse/ ><code>parse</code></a> - deserialize from a compatible input</li> <li><a href=../../api/basic_json_document/parse/ ><code>basic_json_document::parse</code></a> - deserialize into a document instead of a value</li> <li><a href=../../api/basic_json/accept/ ><code>accept</code></a> - check if the input is valid <abbr title="JavaScript Object Notation">JSON</abbr></li> <li><a href=../../api/basic_json/sax_parse/ ><code>sax_parse</code></a> - generate <abbr title="Simple API for XML">SAX</abbr> events</li> <li><a href=json_lines/ ><abbr title="JavaScript Object Notation">JSON</abbr> Lines</a> - parse newline-delimited <abbr title="JavaScript Object Notation">JSON</abbr></li> <li><a href=large_and_partial_input/ >Large, streamed, and partial input</a> - chunked, concatenated, and very large input</li> <li><a href=parser_callbacks/ >parser callbacks</a> - influence the parsing by a callback function</li> <li><a href=sax_interface/ ><abbr title="Simple API for XML">SAX</abbr> interface</a> - implement a custom <abbr title="Simple API for XML">SAX</abbr> handler</li> <li><a href=../json_view/ >Zero-copy <abbr title="JavaScript Object Notation">JSON</abbr> views</a> - parse into a read-only document and read it through views</li> <li><a href=parse_exceptions/ >parsing and exceptions</a> - control error handling</li> <li><a href=untrusted_input/ >parsing untrusted input</a> - what to consider when parsing input from untrusted sources</li> <li><a href=../json_view/ >Zero-copy <abbr title="JavaScript Object Notation">JSON</abbr> views</a> - parse into a document and read it through a view</li> </ul> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="October 25, 2026 11:07:13 UTC">October 25, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> <div class=md-copyright__highlight> Copyright © 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 1Line truncated
|
||||
@@ -32,7 +32,7 @@ std::ifstream f("example.json");
|
||||
json data = json::parse(f);
|
||||
```
|
||||
|
||||
The input must be encoded in UTF-8; other encodings are not supported. The exception is wide-character input, which is read as UTF-16 or UTF-32 -- depending on the character type -- and converted to UTF-8; see the [`parse`](https://json.nlohmann.me/api/basic_json/parse/index.md) page for an example. A single input may contain only one JSON value. Inputs consisting of multiple values separated by newlines are handled by the [JSON Lines](https://json.nlohmann.me/features/parsing/json_lines/index.md) format.
|
||||
The input must be encoded in UTF-8; other encodings are not supported. The exception is wide-character input, which is read as UTF-16 or UTF-32 -- depending on the character type -- and converted to UTF-8; see the [`parse`](https://json.nlohmann.me/api/basic_json/parse/index.md) page for an example. A single input may contain only one JSON value. Inputs consisting of multiple values separated by newlines are handled by the [JSON Lines](https://json.nlohmann.me/features/parsing/json_lines/index.md) format; input that arrives in chunks or contains several values is covered in [Large, streamed, and partial input](https://json.nlohmann.me/features/parsing/large_and_partial_input/index.md).
|
||||
|
||||
By default, the library rejects comments and trailing commas. Both can be enabled with parameters of the `parse` function — see [comments](https://json.nlohmann.me/features/comments/index.md) and [trailing commas](https://json.nlohmann.me/features/trailing_commas/index.md).
|
||||
|
||||
@@ -65,10 +65,11 @@ Where the target has them, strings are scanned with vector instructions: SSE2 on
|
||||
|
||||
## SAX vs. DOM parsing
|
||||
|
||||
The library offers two parsing models:
|
||||
The library offers two parsing models, and a third, read-only alternative:
|
||||
|
||||
- **DOM parsing** (the default): the complete input is read and stored as an in-memory `basic_json` value that can be traversed and modified freely. This is what [`parse`](https://json.nlohmann.me/api/basic_json/parse/index.md) does, and it is the right choice for most use cases.
|
||||
- **SAX parsing**: instead of building a value, the parser reports events (such as "a string was read" or "an object started") to a handler that you implement. This avoids building the full value in memory and is useful for very large inputs or when you only need to extract parts of the input. See the [SAX interface](https://json.nlohmann.me/features/parsing/sax_interface/index.md) for details and [`sax_parse`](https://json.nlohmann.me/api/basic_json/sax_parse/index.md) for the API.
|
||||
- **Document and views** (`<nlohmann/json_view.hpp>`, added in version 3.13.0 unreleased): [`json_document::parse`](https://json.nlohmann.me/api/basic_json_document/parse/index.md) reads the same JSON grammar but builds a flat, read-only index of the values instead of a `basic_json` tree. Strings and floating-point numbers are read from the text on demand, and only the parts you [`materialize()`](https://json.nlohmann.me/api/basic_json_view/materialize/index.md) become `basic_json` values. This avoids most of the work when you need only a few values from a large or frequently parsed text; see [Zero-copy JSON views](https://json.nlohmann.me/features/json_view/index.md). It is read-only, so use `parse` when you need to modify the value.
|
||||
|
||||
You can influence a DOM parse without switching to the SAX interface by passing a [parser callback](https://json.nlohmann.me/features/parsing/parser_callbacks/index.md), which is called during parsing and can, for example, discard parts of the input.
|
||||
|
||||
@@ -96,8 +97,10 @@ When the input is not valid JSON, the `parse` function throws an exception by de
|
||||
- [`accept`](https://json.nlohmann.me/api/basic_json/accept/index.md) - check if the input is valid JSON
|
||||
- [`sax_parse`](https://json.nlohmann.me/api/basic_json/sax_parse/index.md) - generate SAX events
|
||||
- [JSON Lines](https://json.nlohmann.me/features/parsing/json_lines/index.md) - parse newline-delimited JSON
|
||||
- [Large, streamed, and partial input](https://json.nlohmann.me/features/parsing/large_and_partial_input/index.md) - chunked, concatenated, and very large input
|
||||
- [parser callbacks](https://json.nlohmann.me/features/parsing/parser_callbacks/index.md) - influence the parsing by a callback function
|
||||
- [SAX interface](https://json.nlohmann.me/features/parsing/sax_interface/index.md) - implement a custom SAX handler
|
||||
- [Zero-copy JSON views](https://json.nlohmann.me/features/json_view/index.md) - parse into a read-only document and read it through views
|
||||
- [parsing and exceptions](https://json.nlohmann.me/features/parsing/parse_exceptions/index.md) - control error handling
|
||||
- [parsing untrusted input](https://json.nlohmann.me/features/parsing/untrusted_input/index.md) - what to consider when parsing input from untrusted sources
|
||||
- [Zero-copy JSON views](https://json.nlohmann.me/features/json_view/index.md) - parse into a document and read it through a view
|
||||
@@ -29,7 +29,7 @@ JSON Lines input with more than one value is treated as invalid JSON by the [`pa
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
using nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
@@ -44,7 +44,7 @@ JSON Lines input with more than one value is treated as invalid JSON by the [`pa
|
||||
std::string line;
|
||||
while (std::getline(input, line))
|
||||
{
|
||||
std::cout << json::parse(line) << std::endl;
|
||||
std::cout << json::parse(line) << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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/parsing/json_lines/" rel="canonical"><link href=../ rel=prev><link href=../parse_exceptions/ rel=next><link rel=icon href=../../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>JSON Lines - 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=#json-lines 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> JSON Lines </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> </labelLine truncated
|
||||
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=author content="Niels Lohmann"><link href="https://json.nlohmann.me/features/parsing/json_lines/" rel="canonical"><link href=../ rel=prev><link href=../large_and_partial_input/ rel=next><link rel=icon href=../../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>JSON Lines - 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=#json-lines 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> JSON Lines </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> Line truncated
|
||||
<span class=p>{</span><span class=nt>"name"</span><span class=p>:</span><span class=w> </span><span class=s2>"Alexa"</span><span class=p>,</span><span class=w> </span><span class=nt>"wins"</span><span class=p>:</span><span class=w> </span><span class=p>[[</span><span class=s2>"two pair"</span><span class=p>,</span><span class=w> </span><span class=s2>"4♠"</span><span class=p>],</span><span class=w> </span><span class=p>[</span><span class=s2>"two pair"</span><span class=p>,</span><span class=w> </span><span class=s2>"9♠"</span><span class=p>]]}</span>
|
||||
<span class=p>{</span><span class=nt>"name"</span><span class=p>:</span><span class=w> </span><span class=s2>"May"</span><span class=p>,</span><span class=w> </span><span class=nt>"wins"</span><span class=p>:</span><span class=w> </span><span class=p>[]}</span>
|
||||
<span class=p>{</span><span class=nt>"name"</span><span class=p>:</span><span class=w> </span><span class=s2>"Deloise"</span><span class=p>,</span><span class=w> </span><span class=nt>"wins"</span><span class=p>:</span><span class=w> </span><span class=p>[[</span><span class=s2>"three of a kind"</span><span class=p>,</span><span class=w> </span><span class=s2>"5♣"</span><span class=p>]]}</span>
|
||||
@@ -6,7 +6,7 @@
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><iostream></span>
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><nlohmann/json.hpp></span>
|
||||
|
||||
<span class=k>using</span><span class=w> </span><span class=n>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=p>;</span>
|
||||
<span class=k>using</span><span class=w> </span><span class=n>nlohmann</span><span class=o>::</span><span class=n>json</span><span class=p>;</span>
|
||||
|
||||
<span class=kt>int</span><span class=w> </span><span class=nf>main</span><span class=p>()</span>
|
||||
<span class=p>{</span>
|
||||
@@ -21,7 +21,7 @@
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=w> </span><span class=n>line</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=k>while</span><span class=w> </span><span class=p>(</span><span class=n>std</span><span class=o>::</span><span class=n>getline</span><span class=p>(</span><span class=n>input</span><span class=p>,</span><span class=w> </span><span class=n>line</span><span class=p>))</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>parse</span><span class=p>(</span><span class=n>line</span><span class=p>)</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>endl</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>parse</span><span class=p>(</span><span class=n>line</span><span class=p>)</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=p>}</span>
|
||||
</code></pre></div> <p>Output:</p> <div class=highlight><pre><span></span><code><span class=p>{</span><span class=nt>"name"</span><span class=p>:</span><span class=s2>"Gilbert"</span><span class=p>,</span><span class=nt>"wins"</span><span class=p>:[[</span><span class=s2>"straight"</span><span class=p>,</span><span class=s2>"7♣"</span><span class=p>],[</span><span class=s2>"one pair"</span><span class=p>,</span><span class=s2>"10♥"</span><span class=p>]]}</span>
|
||||
|
||||
@@ -27,7 +27,7 @@ The example below demonstrates how JSON Lines can be processed.
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
using nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
@@ -42,7 +42,7 @@ int main()
|
||||
std::string line;
|
||||
while (std::getline(input, line))
|
||||
{
|
||||
std::cout << json::parse(line) << std::endl;
|
||||
std::cout << json::parse(line) << '\n';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -0,0 +1,370 @@
|
||||
# Large, Streamed, and Partial Input
|
||||
|
||||
[`parse`](../../api/basic_json/parse.md) reads exactly one complete JSON value and builds it in memory. It cannot be
|
||||
paused and resumed, and it does not hand back a half-parsed value when the input ends early. This page shows what to do
|
||||
when the input does not fit that model: it arrives in pieces, it contains several values, or it is too large to hold
|
||||
as a `json` value.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["my input is..."] --> B{"several JSON values in one stream?"}
|
||||
B -->|"yes"| C["read them one at a time"]
|
||||
A --> D{"arriving in chunks (socket, pipe)?"}
|
||||
D -->|"yes"| E["frame the messages, or buffer until complete"]
|
||||
A --> F{"too large to keep in memory?"}
|
||||
F -->|"yes"| G["discard parts with a callback, or use SAX"]
|
||||
A --> H{"only a small part is needed?"}
|
||||
H -->|"yes"| I["stop early with SAX, or read through a view"]
|
||||
```
|
||||
|
||||
## Several values in one stream
|
||||
|
||||
For newline-delimited input, read line by line and parse each line, as described in [JSON Lines](json_lines.md). For
|
||||
values that are simply concatenated, [`operator>>`](../../api/operator_gtgt.md) reads one value and leaves the stream
|
||||
positioned after it. Check for the end of the stream before each read, because a read at the end throws:
|
||||
|
||||
??? example "Example: read concatenated values"
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::istringstream input(R"({"a":1} [2,3] 4 "s")");
|
||||
|
||||
// check for the end of the stream before each read, because a read at the end throws
|
||||
json j;
|
||||
while (input >> std::ws && input.peek() != std::char_traits<char>::eof())
|
||||
{
|
||||
input >> j;
|
||||
std::cout << j << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
{"a":1}
|
||||
[2,3]
|
||||
4
|
||||
"s"
|
||||
|
||||
```
|
||||
|
||||
The same works for binary formats. [`from_cbor`](../../api/basic_json/from_cbor.md) and its relatives accept
|
||||
`#!cpp strict = false` to stop after the first value and leave the rest of the stream untouched; `tellg()` then reports
|
||||
how many bytes the value took:
|
||||
|
||||
??? example "Example: read one CBOR value and find out how many bytes it used"
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
// a CBOR value followed by other data
|
||||
const std::vector<std::uint8_t> cbor = json::to_cbor(json{1, 2, 3});
|
||||
std::string data(cbor.begin(), cbor.end());
|
||||
data += "TRAILING";
|
||||
|
||||
std::istringstream input(data);
|
||||
json j = json::from_cbor(input, false); // strict = false: stop after the first value
|
||||
|
||||
std::cout << "value: " << j << '\n';
|
||||
std::cout << "bytes used: " << input.tellg() << '\n';
|
||||
|
||||
std::string rest;
|
||||
input >> rest;
|
||||
std::cout << "remaining input: " << rest << '\n';
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
value: [1,2,3]
|
||||
bytes used: 4
|
||||
remaining input: TRAILING
|
||||
|
||||
```
|
||||
|
||||
## Input arriving in chunks
|
||||
|
||||
A socket, pipe, or HTTP body hands over data in pieces of arbitrary size, and a piece can end in the middle of a
|
||||
number, a string, or an object. The parser does not keep state between calls, so there are two ways to deal with this.
|
||||
|
||||
**Frame the messages.** The most robust approach is a protocol that says where a value ends: one value per line
|
||||
([JSON Lines](json_lines.md)), a length prefix, or a delimiter. Collect the bytes of one message and parse them when
|
||||
the frame is complete. Prefer this whenever you control the protocol.
|
||||
|
||||
**Buffer until the value is complete.** If the data has no framing, append every chunk to a buffer and try to parse
|
||||
it. A parse error at the very end of the buffer means that the input ended prematurely, while an error anywhere else is
|
||||
a real syntax error. The member `byte` of the [`parse_error`](../../home/exceptions.md#jsonexceptionparse_error101)
|
||||
exception is one past the buffer size in the first case:
|
||||
|
||||
??? example "Example: buffer chunks until the value is complete"
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
std::string buffer;
|
||||
|
||||
// call for every chunk; returns true and sets `value` once the buffer holds one complete JSON value
|
||||
bool push(const std::string& chunk, json& value)
|
||||
{
|
||||
buffer += chunk;
|
||||
try
|
||||
{
|
||||
value = json::parse(buffer);
|
||||
buffer.clear();
|
||||
return true;
|
||||
}
|
||||
catch (const json::parse_error& e)
|
||||
{
|
||||
if (e.byte == buffer.size() + 1)
|
||||
{
|
||||
return false; // the input ends prematurely: wait for more data
|
||||
}
|
||||
throw; // a real syntax error
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
json value;
|
||||
const auto chunks = {"{\"na", "me\": \"Ma", "ry\", \"l", "ist\": [1, 2", ", 3]}"};
|
||||
for (const std::string chunk : chunks)
|
||||
{
|
||||
std::cout << "chunk " << chunk << " -> " << (push(chunk, value) ? "complete" : "incomplete") << '\n';
|
||||
}
|
||||
std::cout << value << '\n';
|
||||
|
||||
// a syntax error in the middle is not mistaken for missing data
|
||||
try
|
||||
{
|
||||
push("[1, ]", value);
|
||||
}
|
||||
catch (const json::parse_error& e)
|
||||
{
|
||||
std::cout << e.what() << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
chunk {"na -> incomplete
|
||||
chunk me": "Ma -> incomplete
|
||||
chunk ry", "l -> incomplete
|
||||
chunk ist": [1, 2 -> incomplete
|
||||
chunk , 3]} -> complete
|
||||
{"list":[1,2,3],"name":"Mary"}
|
||||
[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal
|
||||
|
||||
```
|
||||
|
||||
The example feeds a document in five chunks. The first four are reported as incomplete, and a syntax error is reported as
|
||||
such, not as missing data.
|
||||
|
||||
!!! warning "Limits of buffering"
|
||||
|
||||
- The buffer must contain exactly one value. Data that belongs to the next value is a syntax error. Use framing if
|
||||
values follow each other without a separator.
|
||||
- A number at the end of the buffer is a complete value, even if more digits are still to come (`12` may be the
|
||||
start of `123`). Buffering cannot detect this; use framing for top-level numbers.
|
||||
- Every attempt parses the buffer from the beginning, so the total work grows quadratically with the size of the
|
||||
value. Limit the size of the buffer for input you do not trust (see [untrusted input](untrusted_input.md)).
|
||||
|
||||
## Input too large for memory
|
||||
|
||||
The input does not have to become one huge `json` value. The two tools below process it piece by piece.
|
||||
|
||||
### Handle and discard elements with a callback
|
||||
|
||||
A [parser callback](parser_callbacks.md) is called for every finished value. If it returns `#!cpp false`, the value is
|
||||
discarded and its memory is released at once. For a file that consists of one huge array (or one huge object) of
|
||||
records, handle each record at depth 1 and discard it:
|
||||
|
||||
??? example "Example: handle and discard each record of a large array"
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
void handle(const json& record)
|
||||
{
|
||||
std::cout << "handling " << record << '\n';
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::istringstream file(R"([{"id": 1}, {"id": 2}, {"id": 3}])");
|
||||
|
||||
json result = json::parse(file, [](int depth, json::parse_event_t event, json & record)
|
||||
{
|
||||
if (depth == 1 && event == json::parse_event_t::object_end)
|
||||
{
|
||||
handle(record);
|
||||
return false; // discard the record
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
std::cout << "result: " << result << '\n';
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
handling {"id":1}
|
||||
handling {"id":2}
|
||||
handling {"id":3}
|
||||
result: []
|
||||
|
||||
```
|
||||
|
||||
Only one record is in memory at any time. The same recipe, with more detail, is in the
|
||||
[parser callbacks](parser_callbacks.md#recipe-streaming-a-large-homogeneous-array) page. To skip entire members you do not
|
||||
need, discard them when their key is read; see the [example](parser_callbacks.md) for `parse_event_t::key`.
|
||||
|
||||
### Extract a few values and stop with SAX
|
||||
|
||||
With the [SAX interface](sax_interface.md), no value is built at all, and **returning `#!cpp false` from any handler
|
||||
function stops the parser**. [`sax_parse`](../../api/basic_json/sax_parse.md) then returns `#!cpp false`, and the rest
|
||||
of the input is not read. The example finds the first `id` in a document without parsing the remainder:
|
||||
|
||||
??? example "Example: stop parsing as soon as a value is found"
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
struct find_id : nlohmann::json_sax<json>
|
||||
{
|
||||
bool next_is_id = false;
|
||||
json::number_unsigned_t id = 0;
|
||||
|
||||
bool key(std::string& name) override
|
||||
{
|
||||
next_is_id = (name == "id");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_unsigned(json::number_unsigned_t value) override
|
||||
{
|
||||
if (next_is_id)
|
||||
{
|
||||
id = value;
|
||||
return false; // found: stop parsing
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool null() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool boolean(bool /*val*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool number_integer(json::number_integer_t /*val*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool number_float(json::number_float_t /*val*/, const std::string& /*s*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool string(std::string& /*val*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool binary(json::binary_t& /*val*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool start_object(std::size_t /*elements*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool end_object() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool start_array(std::size_t /*elements*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool end_array() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& /*ex*/) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
find_id handler;
|
||||
const bool completed = json::sax_parse(R"({"x": [1, 2, 3], "id": 42, "rest": [4, 5, 6]})", &handler);
|
||||
|
||||
std::cout << std::boolalpha;
|
||||
std::cout << "parse completed: " << completed << '\n';
|
||||
std::cout << "id: " << handler.id << '\n';
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
parse completed: false
|
||||
id: 42
|
||||
|
||||
```
|
||||
|
||||
Note that `sax_parse` returns `#!cpp false` both when a handler stopped the parse and when the input is invalid, so
|
||||
record the reason in the handler (here: `id`) if you need to tell the two apart.
|
||||
|
||||
### Read parts of a large document with a view
|
||||
|
||||
If the whole text is available and you only need to read some of it, a [`json_document`](../json_view.md) from
|
||||
`<nlohmann/json_view.hpp>` (added in version 3.13.0) avoids the `basic_json` tree altogether: it keeps the text, builds a flat index of the values,
|
||||
and gives read-only [views](../../api/basic_json_view/index.md) of the parts you look at. Only what you
|
||||
[`materialize()`](../../api/basic_json_view/materialize.md) becomes a `basic_json` value. See
|
||||
[Zero-copy JSON views](../json_view.md) for details and for the lifetime rules.
|
||||
|
||||
## See also
|
||||
|
||||
- [Parsing](index.md) - overview of the parsing functions
|
||||
- [JSON Lines](json_lines.md) - newline-delimited JSON
|
||||
- [Parser callbacks](parser_callbacks.md) - discard values while parsing
|
||||
- [SAX interface](sax_interface.md) - event-based parsing
|
||||
- [Zero-copy JSON views](../json_view.md) - read parts of a large document without building a tree
|
||||
- [Untrusted input](untrusted_input.md) - limits for input you do not control
|
||||
@@ -0,0 +1,225 @@
|
||||
<!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/parsing/large_and_partial_input/" rel="canonical"><link href=../json_lines/ rel=prev><link href=../parse_exceptions/ rel=next><link rel=icon href=../../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>Large, Streamed, and Partial Input - 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=#large-streamed-and-partial-input class=md-skip> Skip to content </a> </div> <div data-md-component=announce> </div> <header class=md-header data-md-component=header> <nav class="md-header__inner md-grid" aria-label=Header> <a href=../../.. title="JSON for Modern C++" class="md-header__button md-logo" aria-label="JSON for Modern C++" data-md-component=logo> <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> Large, Streamed, and Partial Input </span> </div> </div> </div> <form class=md-header__option data-md-component=palette> <input class=md-option data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme=default data-md-color-primary=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 Line truncated
|
||||
A["my input is..."] --> B{"several JSON values in one stream?"}
|
||||
B -->|"yes"| C["read them one at a time"]
|
||||
A --> D{"arriving in chunks (socket, pipe)?"}
|
||||
D -->|"yes"| E["frame the messages, or buffer until complete"]
|
||||
A --> F{"too large to keep in memory?"}
|
||||
F -->|"yes"| G["discard parts with a callback, or use SAX"]
|
||||
A --> H{"only a small part is needed?"}
|
||||
H -->|"yes"| I["stop early with SAX, or read through a view"]</code></pre> <h2 id=several-values-in-one-stream>Several values in one stream<a class=headerlink href=#several-values-in-one-stream title="Permanent link">¶</a></h2> <p>For newline-delimited input, read line by line and parse each line, as described in <a href=../json_lines/ ><abbr title="JavaScript Object Notation">JSON</abbr> Lines</a>. For values that are simply concatenated, <a href=../../../api/operator_gtgt/ ><code>operator>></code></a> reads one value and leaves the stream positioned after it. Check for the end of the stream before each read, because a read at the end throws:</p> <details class=example> <summary>Example: read concatenated values</summary> <div class=highlight><pre><span></span><code><span class=cp>#include</span><span class=w> </span><span class=cpf><iostream></span>
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><sstream></span>
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><nlohmann/json.hpp></span>
|
||||
|
||||
<span class=k>using</span><span class=w> </span><span class=n>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=p>;</span>
|
||||
|
||||
<span class=kt>int</span><span class=w> </span><span class=nf>main</span><span class=p>()</span>
|
||||
<span class=p>{</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>istringstream</span><span class=w> </span><span class=n>input</span><span class=p>(</span><span class=sa>R</span><span class=s>"</span><span class=dl>(</span><span class=s>{"a":1} [2,3] 4 "s"</span><span class=dl>)</span><span class=s>"</span><span class=p>);</span>
|
||||
|
||||
<span class=w> </span><span class=c1>// check for the end of the stream before each read, because a read at the end throws</span>
|
||||
<span class=w> </span><span class=n>json</span><span class=w> </span><span class=n>j</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=k>while</span><span class=w> </span><span class=p>(</span><span class=n>input</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>ws</span><span class=w> </span><span class=o>&&</span><span class=w> </span><span class=n>input</span><span class=p>.</span><span class=n>peek</span><span class=p>()</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>char_traits</span><span class=o><</span><span class=kt>char</span><span class=o>>::</span><span class=n>eof</span><span class=p>())</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=n>input</span><span class=w> </span><span class=o>>></span><span class=w> </span><span class=n>j</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>j</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=p>}</span>
|
||||
</code></pre></div> <p>Output:</p> <div class=highlight><pre><span></span><code>{"a":1}
|
||||
[2,3]
|
||||
4
|
||||
"s"
|
||||
</code></pre></div> </details> <p>The same works for binary formats. <a href=../../../api/basic_json/from_cbor/ ><code>from_cbor</code></a> and its relatives accept <code class=highlight><span class=n>strict</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=nb>false</span></code> to stop after the first value and leave the rest of the stream untouched; <code>tellg()</code> then reports how many bytes the value took:</p> <details class=example> <summary>Example: read one <abbr title="Concise Binary Object Representation">CBOR</abbr> value and find out how many bytes it used</summary> <div class=highlight><pre><span></span><code><span class=cp>#include</span><span class=w> </span><span class=cpf><iostream></span>
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><sstream></span>
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><nlohmann/json.hpp></span>
|
||||
|
||||
<span class=k>using</span><span class=w> </span><span class=n>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=p>;</span>
|
||||
|
||||
<span class=kt>int</span><span class=w> </span><span class=nf>main</span><span class=p>()</span>
|
||||
<span class=p>{</span>
|
||||
<span class=w> </span><span class=c1>// a CBOR value followed by other data</span>
|
||||
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>vector</span><span class=o><</span><span class=n>std</span><span class=o>::</span><span class=kt>uint8_t</span><span class=o>></span><span class=w> </span><span class=n>cbor</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>to_cbor</span><span class=p>(</span><span class=n>json</span><span class=p>{</span><span class=mi>1</span><span class=p>,</span><span class=w> </span><span class=mi>2</span><span class=p>,</span><span class=w> </span><span class=mi>3</span><span class=p>});</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=w> </span><span class=n>data</span><span class=p>(</span><span class=n>cbor</span><span class=p>.</span><span class=n>begin</span><span class=p>(),</span><span class=w> </span><span class=n>cbor</span><span class=p>.</span><span class=n>end</span><span class=p>());</span>
|
||||
<span class=w> </span><span class=n>data</span><span class=w> </span><span class=o>+=</span><span class=w> </span><span class=s>"TRAILING"</span><span class=p>;</span>
|
||||
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>istringstream</span><span class=w> </span><span class=n>input</span><span class=p>(</span><span class=n>data</span><span class=p>);</span>
|
||||
<span class=w> </span><span class=n>json</span><span class=w> </span><span class=n>j</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>from_cbor</span><span class=p>(</span><span class=n>input</span><span class=p>,</span><span class=w> </span><span class=nb>false</span><span class=p>);</span><span class=w> </span><span class=c1>// strict = false: stop after the first value</span>
|
||||
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"value: "</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>j</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"bytes used: "</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>input</span><span class=p>.</span><span class=n>tellg</span><span class=p>()</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=w> </span><span class=n>rest</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=n>input</span><span class=w> </span><span class=o>>></span><span class=w> </span><span class=n>rest</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"remaining input: "</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>rest</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
<span class=p>}</span>
|
||||
</code></pre></div> <p>Output:</p> <div class=highlight><pre><span></span><code>value: [1,2,3]
|
||||
bytes used: 4
|
||||
remaining input: TRAILING
|
||||
</code></pre></div> </details> <h2 id=input-arriving-in-chunks>Input arriving in chunks<a class=headerlink href=#input-arriving-in-chunks title="Permanent link">¶</a></h2> <p>A socket, pipe, or <abbr title="Hypertext Transfer Protocol">HTTP</abbr> body hands over data in pieces of arbitrary size, and a piece can end in the middle of a number, a string, or an object. The parser does not keep state between calls, so there are two ways to deal with this.</p> <p><strong>Frame the messages.</strong> The most robust approach is a protocol that says where a value ends: one value per line (<a href=../json_lines/ ><abbr title="JavaScript Object Notation">JSON</abbr> Lines</a>), a length prefix, or a delimiter. Collect the bytes of one message and parse them when the frame is complete. Prefer this whenever you control the protocol.</p> <p><strong>Buffer until the value is complete.</strong> If the data has no framing, append every chunk to a buffer and try to parse it. A parse error at the very end of the buffer means that the input ended prematurely, while an error anywhere else is a real syntax error. The member <code>byte</code> of the <a href=../../../home/exceptions/#jsonexceptionparse_error101><code>parse_error</code></a> exception is one past the buffer size in the first case:</p> <details class=example> <summary>Example: buffer chunks until the value is complete</summary> <div class=highlight><pre><span></span><code><span class=cp>#include</span><span class=w> </span><span class=cpf><iostream></span>
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><nlohmann/json.hpp></span>
|
||||
|
||||
<span class=k>using</span><span class=w> </span><span class=n>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=p>;</span>
|
||||
|
||||
<span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=w> </span><span class=n>buffer</span><span class=p>;</span>
|
||||
|
||||
<span class=c1>// call for every chunk; returns true and sets `value` once the buffer holds one complete JSON value</span>
|
||||
<span class=kt>bool</span><span class=w> </span><span class=nf>push</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=o>&</span><span class=w> </span><span class=n>chunk</span><span class=p>,</span><span class=w> </span><span class=n>json</span><span class=o>&</span><span class=w> </span><span class=n>value</span><span class=p>)</span>
|
||||
<span class=p>{</span>
|
||||
<span class=w> </span><span class=n>buffer</span><span class=w> </span><span class=o>+=</span><span class=w> </span><span class=n>chunk</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=k>try</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=n>value</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>parse</span><span class=p>(</span><span class=n>buffer</span><span class=p>);</span>
|
||||
<span class=w> </span><span class=n>buffer</span><span class=p>.</span><span class=n>clear</span><span class=p>();</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>true</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=k>catch</span><span class=w> </span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>parse_error</span><span class=o>&</span><span class=w> </span><span class=n>e</span><span class=p>)</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>if</span><span class=w> </span><span class=p>(</span><span class=n>e</span><span class=p>.</span><span class=kt>byte</span><span class=w> </span><span class=o>==</span><span class=w> </span><span class=n>buffer</span><span class=p>.</span><span class=n>size</span><span class=p>()</span><span class=w> </span><span class=o>+</span><span class=w> </span><span class=mi>1</span><span class=p>)</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>false</span><span class=p>;</span><span class=w> </span><span class=c1>// the input ends prematurely: wait for more data</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=k>throw</span><span class=p>;</span><span class=w> </span><span class=c1>// a real syntax error</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=p>}</span>
|
||||
|
||||
<span class=kt>int</span><span class=w> </span><span class=nf>main</span><span class=p>()</span>
|
||||
<span class=p>{</span>
|
||||
<span class=w> </span><span class=n>json</span><span class=w> </span><span class=n>value</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=k>auto</span><span class=w> </span><span class=n>chunks</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=p>{</span><span class=s>"{</span><span class=se>\"</span><span class=s>na"</span><span class=p>,</span><span class=w> </span><span class=s>"me</span><span class=se>\"</span><span class=s>: </span><span class=se>\"</span><span class=s>Ma"</span><span class=p>,</span><span class=w> </span><span class=s>"ry</span><span class=se>\"</span><span class=s>, </span><span class=se>\"</span><span class=s>l"</span><span class=p>,</span><span class=w> </span><span class=s>"ist</span><span class=se>\"</span><span class=s>: [1, 2"</span><span class=p>,</span><span class=w> </span><span class=s>", 3]}"</span><span class=p>};</span>
|
||||
<span class=w> </span><span class=k>for</span><span class=w> </span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=w> </span><span class=n>chunk</span><span class=w> </span><span class=o>:</span><span class=w> </span><span class=n>chunks</span><span class=p>)</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"chunk "</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>chunk</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>" -> "</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=p>(</span><span class=n>push</span><span class=p>(</span><span class=n>chunk</span><span class=p>,</span><span class=w> </span><span class=n>value</span><span class=p>)</span><span class=w> </span><span class=o>?</span><span class=w> </span><span class=s>"complete"</span><span class=w> </span><span class=o>:</span><span class=w> </span><span class=s>"incomplete"</span><span class=p>)</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>value</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
|
||||
<span class=w> </span><span class=c1>// a syntax error in the middle is not mistaken for missing data</span>
|
||||
<span class=w> </span><span class=k>try</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=n>push</span><span class=p>(</span><span class=s>"[1, ]"</span><span class=p>,</span><span class=w> </span><span class=n>value</span><span class=p>);</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=k>catch</span><span class=w> </span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>parse_error</span><span class=o>&</span><span class=w> </span><span class=n>e</span><span class=p>)</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>e</span><span class=p>.</span><span class=n>what</span><span class=p>()</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=p>}</span>
|
||||
</code></pre></div> <p>Output:</p> <div class=highlight><pre><span></span><code>chunk {"na -> incomplete
|
||||
chunk me": "Ma -> incomplete
|
||||
chunk ry", "l -> incomplete
|
||||
chunk ist": [1, 2 -> incomplete
|
||||
chunk , 3]} -> complete
|
||||
{"list":[1,2,3],"name":"Mary"}
|
||||
[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal
|
||||
</code></pre></div> </details> <p>The example feeds a document in five chunks. The first four are reported as incomplete, and a syntax error is reported as such, not as missing data.</p> <div class="admonition warning"> <p class=admonition-title>Limits of buffering</p> <ul> <li>The buffer must contain exactly one value. Data that belongs to the next value is a syntax error. Use framing if values follow each other without a separator.</li> <li>A number at the end of the buffer is a complete value, even if more digits are still to come (<code>12</code> may be the start of <code>123</code>). Buffering cannot detect this; use framing for top-level numbers.</li> <li>Every attempt parses the buffer from the beginning, so the total work grows quadratically with the size of the value. Limit the size of the buffer for input you do not trust (see <a href=../untrusted_input/ >untrusted input</a>).</li> </ul> </div> <h2 id=input-too-large-for-memory>Input too large for memory<a class=headerlink href=#input-too-large-for-memory title="Permanent link">¶</a></h2> <p>The input does not have to become one huge <code>json</code> value. The two tools below process it piece by piece.</p> <h3 id=handle-and-discard-elements-with-a-callback>Handle and discard elements with a callback<a class=headerlink href=#handle-and-discard-elements-with-a-callback title="Permanent link">¶</a></h3> <p>A <a href=../parser_callbacks/ >parser callback</a> is called for every finished value. If it returns <code class=highlight><span class=nb>false</span></code>, the value is discarded and its memory is released at once. For a file that consists of one huge array (or one huge object) of records, handle each record at depth 1 and discard it:</p> <details class=example> <summary>Example: handle and discard each record of a large array</summary> <div class=highlight><pre><span></span><code><span class=cp>#include</span><span class=w> </span><span class=cpf><iostream></span>
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><sstream></span>
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><nlohmann/json.hpp></span>
|
||||
|
||||
<span class=k>using</span><span class=w> </span><span class=n>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=p>;</span>
|
||||
|
||||
<span class=kt>void</span><span class=w> </span><span class=nf>handle</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>json</span><span class=o>&</span><span class=w> </span><span class=n>record</span><span class=p>)</span>
|
||||
<span class=p>{</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"handling "</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>record</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
<span class=p>}</span>
|
||||
|
||||
<span class=kt>int</span><span class=w> </span><span class=nf>main</span><span class=p>()</span>
|
||||
<span class=p>{</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>istringstream</span><span class=w> </span><span class=n>file</span><span class=p>(</span><span class=sa>R</span><span class=s>"</span><span class=dl>(</span><span class=s>[{"id": 1}, {"id": 2}, {"id": 3}]</span><span class=dl>)</span><span class=s>"</span><span class=p>);</span>
|
||||
|
||||
<span class=w> </span><span class=n>json</span><span class=w> </span><span class=n>result</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>parse</span><span class=p>(</span><span class=n>file</span><span class=p>,</span><span class=w> </span><span class=p>[](</span><span class=kt>int</span><span class=w> </span><span class=n>depth</span><span class=p>,</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>parse_event_t</span><span class=w> </span><span class=n>event</span><span class=p>,</span><span class=w> </span><span class=n>json</span><span class=w> </span><span class=o>&</span><span class=w> </span><span class=n>record</span><span class=p>)</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>if</span><span class=w> </span><span class=p>(</span><span class=n>depth</span><span class=w> </span><span class=o>==</span><span class=w> </span><span class=mi>1</span><span class=w> </span><span class=o>&&</span><span class=w> </span><span class=n>event</span><span class=w> </span><span class=o>==</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>parse_event_t</span><span class=o>::</span><span class=n>object_end</span><span class=p>)</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=n>handle</span><span class=p>(</span><span class=n>record</span><span class=p>);</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>false</span><span class=p>;</span><span class=w> </span><span class=c1>// discard the record</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>true</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>});</span>
|
||||
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"result: "</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>result</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
<span class=p>}</span>
|
||||
</code></pre></div> <p>Output:</p> <div class=highlight><pre><span></span><code>handling {"id":1}
|
||||
handling {"id":2}
|
||||
handling {"id":3}
|
||||
result: []
|
||||
</code></pre></div> </details> <p>Only one record is in memory at any time. The same recipe, with more detail, is in the <a href=../parser_callbacks/#recipe-streaming-a-large-homogeneous-array>parser callbacks</a> page. To skip entire members you do not need, discard them when their key is read; see the <a href=../parser_callbacks/ >example</a> for <code>parse_event_t::key</code>.</p> <h3 id=extract-a-few-values-and-stop-with-sax>Extract a few values and stop with <abbr title="Simple API for XML">SAX</abbr><a class=headerlink href=#extract-a-few-values-and-stop-with-sax title="Permanent link">¶</a></h3> <p>With the <a href=../sax_interface/ ><abbr title="Simple API for XML">SAX</abbr> interface</a>, no value is built at all, and <strong>returning <code class=highlight><span class=nb>false</span></code> from any handler function stops the parser</strong>. <a href=../../../api/basic_json/sax_parse/ ><code>sax_parse</code></a> then returns <code class=highlight><span class=nb>false</span></code>, and the rest of the input is not read. The example finds the first <code>id</code> in a document without parsing the remainder:</p> <details class=example> <summary>Example: stop parsing as soon as a value is found</summary> <div class=highlight><pre><span></span><code><span class=cp>#include</span><span class=w> </span><span class=cpf><iostream></span>
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><nlohmann/json.hpp></span>
|
||||
|
||||
<span class=k>using</span><span class=w> </span><span class=n>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=p>;</span>
|
||||
|
||||
<span class=k>struct</span><span class=w> </span><span class=nc>find_id</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_sax</span><span class=o><</span><span class=n>json</span><span class=o>></span>
|
||||
<span class=p>{</span>
|
||||
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=n>next_is_id</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=nb>false</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>number_unsigned_t</span><span class=w> </span><span class=n>id</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=mi>0</span><span class=p>;</span>
|
||||
|
||||
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=nf>key</span><span class=p>(</span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=o>&</span><span class=w> </span><span class=n>name</span><span class=p>)</span><span class=w> </span><span class=k>override</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=n>next_is_id</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=p>(</span><span class=n>name</span><span class=w> </span><span class=o>==</span><span class=w> </span><span class=s>"id"</span><span class=p>);</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>true</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
|
||||
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=nf>number_unsigned</span><span class=p>(</span><span class=n>json</span><span class=o>::</span><span class=n>number_unsigned_t</span><span class=w> </span><span class=n>value</span><span class=p>)</span><span class=w> </span><span class=k>override</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>if</span><span class=w> </span><span class=p>(</span><span class=n>next_is_id</span><span class=p>)</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=n>id</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>value</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>false</span><span class=p>;</span><span class=w> </span><span class=c1>// found: stop parsing</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>true</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
|
||||
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=nf>null</span><span class=p>()</span><span class=w> </span><span class=k>override</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>true</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=nf>boolean</span><span class=p>(</span><span class=kt>bool</span><span class=w> </span><span class=cm>/*val*/</span><span class=p>)</span><span class=w> </span><span class=k>override</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>true</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=nf>number_integer</span><span class=p>(</span><span class=n>json</span><span class=o>::</span><span class=n>number_integer_t</span><span class=w> </span><span class=cm>/*val*/</span><span class=p>)</span><span class=w> </span><span class=k>override</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>true</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=nf>number_float</span><span class=p>(</span><span class=n>json</span><span class=o>::</span><span class=n>number_float_t</span><span class=w> </span><span class=cm>/*val*/</span><span class=p>,</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=o>&</span><span class=w> </span><span class=cm>/*s*/</span><span class=p>)</span><span class=w> </span><span class=k>override</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>true</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=nf>string</span><span class=p>(</span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=o>&</span><span class=w> </span><span class=cm>/*val*/</span><span class=p>)</span><span class=w> </span><span class=k>override</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>true</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=nf>binary</span><span class=p>(</span><span class=n>json</span><span class=o>::</span><span class=n>binary_t</span><span class=o>&</span><span class=w> </span><span class=cm>/*val*/</span><span class=p>)</span><span class=w> </span><span class=k>override</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>true</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=nf>start_object</span><span class=p>(</span><span class=n>std</span><span class=o>::</span><span class=kt>size_t</span><span class=w> </span><span class=cm>/*elements*/</span><span class=p>)</span><span class=w> </span><span class=k>override</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>true</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=nf>end_object</span><span class=p>()</span><span class=w> </span><span class=k>override</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>true</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=nf>start_array</span><span class=p>(</span><span class=n>std</span><span class=o>::</span><span class=kt>size_t</span><span class=w> </span><span class=cm>/*elements*/</span><span class=p>)</span><span class=w> </span><span class=k>override</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>true</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=nf>end_array</span><span class=p>()</span><span class=w> </span><span class=k>override</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>true</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=nf>parse_error</span><span class=p>(</span><span class=n>std</span><span class=o>::</span><span class=kt>size_t</span><span class=w> </span><span class=cm>/*position*/</span><span class=p>,</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=o>&</span><span class=w> </span><span class=cm>/*last_token*/</span><span class=p>,</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>exception</span><span class=o>&</span><span class=w> </span><span class=cm>/*ex*/</span><span class=p>)</span><span class=w> </span><span class=k>override</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>false</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=p>};</span>
|
||||
|
||||
<span class=kt>int</span><span class=w> </span><span class=nf>main</span><span class=p>()</span>
|
||||
<span class=p>{</span>
|
||||
<span class=w> </span><span class=n>find_id</span><span class=w> </span><span class=n>handler</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=n>completed</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>sax_parse</span><span class=p>(</span><span class=sa>R</span><span class=s>"</span><span class=dl>(</span><span class=s>{"x": [1, 2, 3], "id": 42, "rest": [4, 5, 6]}</span><span class=dl>)</span><span class=s>"</span><span class=p>,</span><span class=w> </span><span class=o>&</span><span class=n>handler</span><span class=p>);</span>
|
||||
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>boolalpha</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"parse completed: "</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>completed</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"id: "</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>handler</span><span class=p>.</span><span class=n>id</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
<span class=p>}</span>
|
||||
</code></pre></div> <p>Output:</p> <div class=highlight><pre><span></span><code>parse completed: false
|
||||
id: 42
|
||||
</code></pre></div> </details> <p>Note that <code>sax_parse</code> returns <code class=highlight><span class=nb>false</span></code> both when a handler stopped the parse and when the input is invalid, so record the reason in the handler (here: <code>id</code>) if you need to tell the two apart.</p> <h3 id=read-parts-of-a-large-document-with-a-view>Read parts of a large document with a view<a class=headerlink href=#read-parts-of-a-large-document-with-a-view title="Permanent link">¶</a></h3> <p>If the whole text is available and you only need to read some of it, a <a href=../../json_view/ ><code>json_document</code></a> from <code><nlohmann/json_view.hpp></code> (added in version 3.13.0 <span class=unreleased-version title="Not part of a release yet; the latest release is 3.12.0.">unreleased</span>) avoids the <code>basic_json</code> tree altogether: it keeps the text, builds a flat index of the values, and gives read-only <a href=../../../api/basic_json_view/ >views</a> of the parts you look at. Only what you <a href=../../../api/basic_json_view/materialize/ ><code>materialize()</code></a> becomes a <code>basic_json</code> value. See <a href=../../json_view/ >Zero-copy <abbr title="JavaScript Object Notation">JSON</abbr> views</a> for details and for the lifetime rules.</p> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">¶</a></h2> <ul> <li><a href=../ >Parsing</a> - overview of the parsing functions</li> <li><a href=../json_lines/ ><abbr title="JavaScript Object Notation">JSON</abbr> Lines</a> - newline-delimited <abbr title="JavaScript Object Notation">JSON</abbr></li> <li><a href=../parser_callbacks/ >Parser callbacks</a> - discard values while parsing</li> <li><a href=../sax_interface/ ><abbr title="Simple API for XML">SAX</abbr> interface</a> - event-based parsing</li> <li><a href=../../json_view/ >Zero-copy <abbr title="JavaScript Object Notation">JSON</abbr> views</a> - read parts of a large document without building a tree</li> <li><a href=../untrusted_input/ >Untrusted input</a> - limits for input you do not control</li> </ul> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="October 25, 2026 11:07:13 UTC">October 25, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> <div class=md-copyright__highlight> Copyright © 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.Line truncated
|
||||
@@ -0,0 +1,332 @@
|
||||
# Large, Streamed, and Partial Input
|
||||
|
||||
[`parse`](https://json.nlohmann.me/api/basic_json/parse/index.md) reads exactly one complete JSON value and builds it in memory. It cannot be paused and resumed, and it does not hand back a half-parsed value when the input ends early. This page shows what to do when the input does not fit that model: it arrives in pieces, it contains several values, or it is too large to hold as a `json` value.
|
||||
|
||||
```
|
||||
flowchart TD
|
||||
A["my input is..."] --> B{"several JSON values in one stream?"}
|
||||
B -->|"yes"| C["read them one at a time"]
|
||||
A --> D{"arriving in chunks (socket, pipe)?"}
|
||||
D -->|"yes"| E["frame the messages, or buffer until complete"]
|
||||
A --> F{"too large to keep in memory?"}
|
||||
F -->|"yes"| G["discard parts with a callback, or use SAX"]
|
||||
A --> H{"only a small part is needed?"}
|
||||
H -->|"yes"| I["stop early with SAX, or read through a view"]
|
||||
```
|
||||
|
||||
## Several values in one stream
|
||||
|
||||
For newline-delimited input, read line by line and parse each line, as described in [JSON Lines](https://json.nlohmann.me/features/parsing/json_lines/index.md). For values that are simply concatenated, [`operator>>`](https://json.nlohmann.me/api/operator_gtgt/index.md) reads one value and leaves the stream positioned after it. Check for the end of the stream before each read, because a read at the end throws:
|
||||
|
||||
Example: read concatenated values
|
||||
|
||||
```
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::istringstream input(R"({"a":1} [2,3] 4 "s")");
|
||||
|
||||
// check for the end of the stream before each read, because a read at the end throws
|
||||
json j;
|
||||
while (input >> std::ws && input.peek() != std::char_traits<char>::eof())
|
||||
{
|
||||
input >> j;
|
||||
std::cout << j << '\n';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
{"a":1}
|
||||
[2,3]
|
||||
4
|
||||
"s"
|
||||
```
|
||||
|
||||
The same works for binary formats. [`from_cbor`](https://json.nlohmann.me/api/basic_json/from_cbor/index.md) and its relatives accept `strict = false` to stop after the first value and leave the rest of the stream untouched; `tellg()` then reports how many bytes the value took:
|
||||
|
||||
Example: read one CBOR value and find out how many bytes it used
|
||||
|
||||
```
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
// a CBOR value followed by other data
|
||||
const std::vector<std::uint8_t> cbor = json::to_cbor(json{1, 2, 3});
|
||||
std::string data(cbor.begin(), cbor.end());
|
||||
data += "TRAILING";
|
||||
|
||||
std::istringstream input(data);
|
||||
json j = json::from_cbor(input, false); // strict = false: stop after the first value
|
||||
|
||||
std::cout << "value: " << j << '\n';
|
||||
std::cout << "bytes used: " << input.tellg() << '\n';
|
||||
|
||||
std::string rest;
|
||||
input >> rest;
|
||||
std::cout << "remaining input: " << rest << '\n';
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
value: [1,2,3]
|
||||
bytes used: 4
|
||||
remaining input: TRAILING
|
||||
```
|
||||
|
||||
## Input arriving in chunks
|
||||
|
||||
A socket, pipe, or HTTP body hands over data in pieces of arbitrary size, and a piece can end in the middle of a number, a string, or an object. The parser does not keep state between calls, so there are two ways to deal with this.
|
||||
|
||||
**Frame the messages.** The most robust approach is a protocol that says where a value ends: one value per line ([JSON Lines](https://json.nlohmann.me/features/parsing/json_lines/index.md)), a length prefix, or a delimiter. Collect the bytes of one message and parse them when the frame is complete. Prefer this whenever you control the protocol.
|
||||
|
||||
**Buffer until the value is complete.** If the data has no framing, append every chunk to a buffer and try to parse it. A parse error at the very end of the buffer means that the input ended prematurely, while an error anywhere else is a real syntax error. The member `byte` of the [`parse_error`](https://json.nlohmann.me/home/exceptions/#jsonexceptionparse_error101) exception is one past the buffer size in the first case:
|
||||
|
||||
Example: buffer chunks until the value is complete
|
||||
|
||||
```
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
std::string buffer;
|
||||
|
||||
// call for every chunk; returns true and sets `value` once the buffer holds one complete JSON value
|
||||
bool push(const std::string& chunk, json& value)
|
||||
{
|
||||
buffer += chunk;
|
||||
try
|
||||
{
|
||||
value = json::parse(buffer);
|
||||
buffer.clear();
|
||||
return true;
|
||||
}
|
||||
catch (const json::parse_error& e)
|
||||
{
|
||||
if (e.byte == buffer.size() + 1)
|
||||
{
|
||||
return false; // the input ends prematurely: wait for more data
|
||||
}
|
||||
throw; // a real syntax error
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
json value;
|
||||
const auto chunks = {"{\"na", "me\": \"Ma", "ry\", \"l", "ist\": [1, 2", ", 3]}"};
|
||||
for (const std::string chunk : chunks)
|
||||
{
|
||||
std::cout << "chunk " << chunk << " -> " << (push(chunk, value) ? "complete" : "incomplete") << '\n';
|
||||
}
|
||||
std::cout << value << '\n';
|
||||
|
||||
// a syntax error in the middle is not mistaken for missing data
|
||||
try
|
||||
{
|
||||
push("[1, ]", value);
|
||||
}
|
||||
catch (const json::parse_error& e)
|
||||
{
|
||||
std::cout << e.what() << '\n';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
chunk {"na -> incomplete
|
||||
chunk me": "Ma -> incomplete
|
||||
chunk ry", "l -> incomplete
|
||||
chunk ist": [1, 2 -> incomplete
|
||||
chunk , 3]} -> complete
|
||||
{"list":[1,2,3],"name":"Mary"}
|
||||
[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal
|
||||
```
|
||||
|
||||
The example feeds a document in five chunks. The first four are reported as incomplete, and a syntax error is reported as such, not as missing data.
|
||||
|
||||
Limits of buffering
|
||||
|
||||
- The buffer must contain exactly one value. Data that belongs to the next value is a syntax error. Use framing if values follow each other without a separator.
|
||||
- A number at the end of the buffer is a complete value, even if more digits are still to come (`12` may be the start of `123`). Buffering cannot detect this; use framing for top-level numbers.
|
||||
- Every attempt parses the buffer from the beginning, so the total work grows quadratically with the size of the value. Limit the size of the buffer for input you do not trust (see [untrusted input](https://json.nlohmann.me/features/parsing/untrusted_input/index.md)).
|
||||
|
||||
## Input too large for memory
|
||||
|
||||
The input does not have to become one huge `json` value. The two tools below process it piece by piece.
|
||||
|
||||
### Handle and discard elements with a callback
|
||||
|
||||
A [parser callback](https://json.nlohmann.me/features/parsing/parser_callbacks/index.md) is called for every finished value. If it returns `false`, the value is discarded and its memory is released at once. For a file that consists of one huge array (or one huge object) of records, handle each record at depth 1 and discard it:
|
||||
|
||||
Example: handle and discard each record of a large array
|
||||
|
||||
```
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
void handle(const json& record)
|
||||
{
|
||||
std::cout << "handling " << record << '\n';
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::istringstream file(R"([{"id": 1}, {"id": 2}, {"id": 3}])");
|
||||
|
||||
json result = json::parse(file, [](int depth, json::parse_event_t event, json & record)
|
||||
{
|
||||
if (depth == 1 && event == json::parse_event_t::object_end)
|
||||
{
|
||||
handle(record);
|
||||
return false; // discard the record
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
std::cout << "result: " << result << '\n';
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
handling {"id":1}
|
||||
handling {"id":2}
|
||||
handling {"id":3}
|
||||
result: []
|
||||
```
|
||||
|
||||
Only one record is in memory at any time. The same recipe, with more detail, is in the [parser callbacks](https://json.nlohmann.me/features/parsing/parser_callbacks/#recipe-streaming-a-large-homogeneous-array) page. To skip entire members you do not need, discard them when their key is read; see the [example](https://json.nlohmann.me/features/parsing/parser_callbacks/index.md) for `parse_event_t::key`.
|
||||
|
||||
### Extract a few values and stop with SAX
|
||||
|
||||
With the [SAX interface](https://json.nlohmann.me/features/parsing/sax_interface/index.md), no value is built at all, and **returning `false` from any handler function stops the parser**. [`sax_parse`](https://json.nlohmann.me/api/basic_json/sax_parse/index.md) then returns `false`, and the rest of the input is not read. The example finds the first `id` in a document without parsing the remainder:
|
||||
|
||||
Example: stop parsing as soon as a value is found
|
||||
|
||||
```
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
struct find_id : nlohmann::json_sax<json>
|
||||
{
|
||||
bool next_is_id = false;
|
||||
json::number_unsigned_t id = 0;
|
||||
|
||||
bool key(std::string& name) override
|
||||
{
|
||||
next_is_id = (name == "id");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_unsigned(json::number_unsigned_t value) override
|
||||
{
|
||||
if (next_is_id)
|
||||
{
|
||||
id = value;
|
||||
return false; // found: stop parsing
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool null() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool boolean(bool /*val*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool number_integer(json::number_integer_t /*val*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool number_float(json::number_float_t /*val*/, const std::string& /*s*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool string(std::string& /*val*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool binary(json::binary_t& /*val*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool start_object(std::size_t /*elements*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool end_object() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool start_array(std::size_t /*elements*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool end_array() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& /*ex*/) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
find_id handler;
|
||||
const bool completed = json::sax_parse(R"({"x": [1, 2, 3], "id": 42, "rest": [4, 5, 6]})", &handler);
|
||||
|
||||
std::cout << std::boolalpha;
|
||||
std::cout << "parse completed: " << completed << '\n';
|
||||
std::cout << "id: " << handler.id << '\n';
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
parse completed: false
|
||||
id: 42
|
||||
```
|
||||
|
||||
Note that `sax_parse` returns `false` both when a handler stopped the parse and when the input is invalid, so record the reason in the handler (here: `id`) if you need to tell the two apart.
|
||||
|
||||
### Read parts of a large document with a view
|
||||
|
||||
If the whole text is available and you only need to read some of it, a [`json_document`](https://json.nlohmann.me/features/json_view/index.md) from `<nlohmann/json_view.hpp>` (added in version 3.13.0 unreleased) avoids the `basic_json` tree altogether: it keeps the text, builds a flat index of the values, and gives read-only [views](https://json.nlohmann.me/api/basic_json_view/index.md) of the parts you look at. Only what you [`materialize()`](https://json.nlohmann.me/api/basic_json_view/materialize/index.md) becomes a `basic_json` value. See [Zero-copy JSON views](https://json.nlohmann.me/features/json_view/index.md) for details and for the lifetime rules.
|
||||
|
||||
## See also
|
||||
|
||||
- [Parsing](https://json.nlohmann.me/features/parsing/index.md) - overview of the parsing functions
|
||||
- [JSON Lines](https://json.nlohmann.me/features/parsing/json_lines/index.md) - newline-delimited JSON
|
||||
- [Parser callbacks](https://json.nlohmann.me/features/parsing/parser_callbacks/index.md) - discard values while parsing
|
||||
- [SAX interface](https://json.nlohmann.me/features/parsing/sax_interface/index.md) - event-based parsing
|
||||
- [Zero-copy JSON views](https://json.nlohmann.me/features/json_view/index.md) - read parts of a large document without building a tree
|
||||
- [Untrusted input](https://json.nlohmann.me/features/parsing/untrusted_input/index.md) - limits for input you do not control
|
||||
@@ -21,6 +21,10 @@ catch (json::parse_error& ex)
|
||||
In case exceptions are undesired or not supported by the environment, there are different ways to proceed:
|
||||
|
||||
|
||||
!!! tip
|
||||
|
||||
[Working without exceptions](../no_exceptions.md) also covers accessing values and converting to your own types.
|
||||
|
||||
## Switch off exceptions
|
||||
|
||||
The [`parse()`](../../api/basic_json/parse.md) function accepts a `#!cpp bool` parameter `allow_exceptions` which
|
||||
@@ -76,7 +80,7 @@ The return value indicates whether the parsing should continue, so the function
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
using nlohmann::json;
|
||||
|
||||
// a DOM parser that reports parse errors instead of throwing
|
||||
class sax_no_exception : public nlohmann::detail::json_sax_dom_parser<json, nlohmann::detail::string_input_adapter_type>
|
||||
@@ -93,7 +97,7 @@ The return value indicates whether the parsing should continue, so the function
|
||||
std::cout << "parse error at input byte " << position << "\n"
|
||||
<< ex.what() << "\n"
|
||||
<< "last read: \"" << last_token << "\""
|
||||
<< std::endl;
|
||||
<< '\n';
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -108,10 +112,10 @@ The return value indicates whether the parsing should continue, so the function
|
||||
bool parse_result = json::sax_parse(myinput, &sax);
|
||||
if (!parse_result)
|
||||
{
|
||||
std::cout << "parsing unsuccessful!" << std::endl;
|
||||
std::cout << "parsing unsuccessful!" << '\n';
|
||||
}
|
||||
|
||||
std::cout << "parsed value: " << result << std::endl;
|
||||
std::cout << "parsed value: " << result << '\n';
|
||||
}
|
||||
|
||||
```
|
||||
@@ -126,3 +130,153 @@ The return value indicates whether the parsing should continue, so the function
|
||||
parsed value: [1,2,3]
|
||||
|
||||
```
|
||||
|
||||
## Where did the error occur?
|
||||
|
||||
The message of a [`parse_error`](../../home/exceptions.md#jsonexceptionparse_error101) for JSON text contains the line
|
||||
and column of the error:
|
||||
|
||||
```
|
||||
[json.exception.parse_error.101] parse error at line 3, column 8: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal
|
||||
```
|
||||
|
||||
The exception object itself only stores the **byte index** of the last read character in the member `byte` (the first
|
||||
byte of the input has index 1). The same index is passed to `parse_error` in the [SAX interface](sax_interface.md). If
|
||||
you need the line and column as numbers, for example to show them in an editor, compute them from the input:
|
||||
|
||||
??? example "Example: compute line and column of a parse error"
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
// line and column (both starting at 1) of a byte index in a text
|
||||
std::pair<std::size_t, std::size_t> line_column(const std::string& input, std::size_t byte)
|
||||
{
|
||||
std::size_t line = 1;
|
||||
std::size_t column = 1;
|
||||
for (std::size_t i = 0; i + 1 < byte && i < input.size(); ++i)
|
||||
{
|
||||
if (input[i] == '\n')
|
||||
{
|
||||
++line;
|
||||
column = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
++column;
|
||||
}
|
||||
}
|
||||
return {line, column};
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const std::string input = "{\n \"a\": 1,\n \"b\": ]\n}";
|
||||
|
||||
try
|
||||
{
|
||||
const json j = json::parse(input);
|
||||
std::cout << j << '\n';
|
||||
}
|
||||
catch (const json::parse_error& e)
|
||||
{
|
||||
const auto position = line_column(input, e.byte);
|
||||
std::cout << e.what() << '\n';
|
||||
std::cout << "byte " << e.byte << " = line " << position.first << ", column " << position.second << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
[json.exception.parse_error.101] parse error at line 3, column 8: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal
|
||||
byte 20 = line 3, column 8
|
||||
|
||||
```
|
||||
|
||||
Columns count bytes, so a line with multi-byte UTF-8 characters before the error may differ from the column your editor
|
||||
shows.
|
||||
|
||||
### Where is the value that caused a later error?
|
||||
|
||||
A `parse_error` is raised while the text is read. Many mistakes show up later: the text is valid JSON, but a value has
|
||||
the wrong type when you convert it (`type_error.302`), or a key is missing (`out_of_range.403`). The exception then says
|
||||
what is wrong, but not where in the input the value was. Define
|
||||
[`JSON_DIAGNOSTIC_POSITIONS`](../../api/macros/json_diagnostic_positions.md) before including the library to add the
|
||||
byte range of the offending value to such messages (since version 3.12.0), and to query the range of any value with
|
||||
[`start_pos()`](../../api/basic_json/start_pos.md) and [`end_pos()`](../../api/basic_json/end_pos.md):
|
||||
|
||||
??? example "Example: locate a value with diagnostic positions"
|
||||
|
||||
```cpp
|
||||
#define JSON_DIAGNOSTIC_POSITIONS 1
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
// line and column (both starting at 1) of a byte index in a text
|
||||
std::pair<std::size_t, std::size_t> line_column(const std::string& input, std::size_t byte)
|
||||
{
|
||||
std::size_t line = 1;
|
||||
std::size_t column = 1;
|
||||
for (std::size_t i = 0; i + 1 < byte && i < input.size(); ++i)
|
||||
{
|
||||
if (input[i] == '\n')
|
||||
{
|
||||
++line;
|
||||
column = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
++column;
|
||||
}
|
||||
}
|
||||
return {line, column};
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const std::string input = "{\n \"name\": \"Mary\",\n \"age\": \"forty-two\"\n}";
|
||||
const json j = json::parse(input); // the input is valid JSON ...
|
||||
|
||||
try
|
||||
{
|
||||
const int age = j["age"]; // ... but the value has the wrong type
|
||||
std::cout << age << '\n';
|
||||
}
|
||||
catch (const json::exception& e)
|
||||
{
|
||||
std::cout << e.what() << '\n';
|
||||
|
||||
// start_pos() is a 0-based index into the input; the helper expects a 1-based byte index
|
||||
const auto position = line_column(input, j["age"].start_pos() + 1);
|
||||
std::cout << "the value starts at line " << position.first << ", column " << position.second << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
[json.exception.type_error.302] (bytes 29-40) type must be number, but is string
|
||||
the value starts at line 3, column 10
|
||||
|
||||
```
|
||||
|
||||
Positions are only available for values created by [`parse`](../../api/basic_json/parse.md), they are not updated when a
|
||||
value is changed, and the macro makes every value 16 bytes larger on 64-bit platforms, so use it where the cost is
|
||||
acceptable, for example for configuration files. Note that `start_pos()` is a 0-based index into the input, whereas
|
||||
`byte` of a `parse_error` starts at 1.
|
||||
|
||||
For binary formats such as CBOR, there are no lines; `byte` is the position in the byte sequence. To find out how many
|
||||
bytes a successfully parsed value used, see
|
||||
[Several values in one stream](large_and_partial_input.md#several-values-in-one-stream).
|
||||
@@ -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/parsing/parse_exceptions/" rel="canonical"><link href=../json_lines/ rel=prev><link href=../parser_callbacks/ rel=next><link rel=icon href=../../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>Parsing and Exceptions - 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=#parsing-and-exceptions 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> Parsing and Exceptions </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.5Line truncated
|
||||
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=author content="Niels Lohmann"><link href="https://json.nlohmann.me/features/parsing/parse_exceptions/" rel="canonical"><link href=../large_and_partial_input/ rel=prev><link href=../parser_callbacks/ rel=next><link rel=icon href=../../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>Parsing and Exceptions - 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=#parsing-and-exceptions 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> Parsing and Exceptions </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 2CLine truncated
|
||||
<span class=k>try</span>
|
||||
<span class=p>{</span>
|
||||
<span class=w> </span><span class=n>j</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>parse</span><span class=p>(</span><span class=n>my_input</span><span class=p>);</span>
|
||||
@@ -7,7 +7,7 @@
|
||||
<span class=p>{</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cerr</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"parse error at byte "</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>ex</span><span class=p>.</span><span class=kt>byte</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>endl</span><span class=p>;</span>
|
||||
<span class=p>}</span>
|
||||
</code></pre></div> <p>In case exceptions are undesired or not supported by the environment, there are different ways to proceed:</p> <h2 id=switch-off-exceptions>Switch off exceptions<a class=headerlink href=#switch-off-exceptions title="Permanent link">¶</a></h2> <p>The <a href=../../../api/basic_json/parse/ ><code>parse()</code></a> function accepts a <code class=highlight><span class=kt>bool</span></code> parameter <code>allow_exceptions</code> which controls whether an exception is thrown when a parse error occurs (<code class=highlight><span class=nb>true</span></code>, default) or whether a discarded value should be returned (<code class=highlight><span class=nb>false</span></code>).</p> <div class=highlight><pre><span></span><code><span class=n>json</span><span class=w> </span><span class=n>j</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>parse</span><span class=p>(</span><span class=n>my_input</span><span class=p>,</span><span class=w> </span><span class=nb>nullptr</span><span class=p>,</span><span class=w> </span><span class=nb>false</span><span class=p>);</span>
|
||||
</code></pre></div> <p>In case exceptions are undesired or not supported by the environment, there are different ways to proceed:</p> <div class="admonition tip"> <p class=admonition-title>Tip</p> <p><a href=../../no_exceptions/ >Working without exceptions</a> also covers accessing values and converting to your own types.</p> </div> <h2 id=switch-off-exceptions>Switch off exceptions<a class=headerlink href=#switch-off-exceptions title="Permanent link">¶</a></h2> <p>The <a href=../../../api/basic_json/parse/ ><code>parse()</code></a> function accepts a <code class=highlight><span class=kt>bool</span></code> parameter <code>allow_exceptions</code> which controls whether an exception is thrown when a parse error occurs (<code class=highlight><span class=nb>true</span></code>, default) or whether a discarded value should be returned (<code class=highlight><span class=nb>false</span></code>).</p> <div class=highlight><pre><span></span><code><span class=n>json</span><span class=w> </span><span class=n>j</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>parse</span><span class=p>(</span><span class=n>my_input</span><span class=p>,</span><span class=w> </span><span class=nb>nullptr</span><span class=p>,</span><span class=w> </span><span class=nb>false</span><span class=p>);</span>
|
||||
<span class=k>if</span><span class=w> </span><span class=p>(</span><span class=n>j</span><span class=p>.</span><span class=n>is_discarded</span><span class=p>())</span>
|
||||
<span class=p>{</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cerr</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"parse error"</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>endl</span><span class=p>;</span>
|
||||
@@ -22,7 +22,7 @@
|
||||
</code></pre></div> <p>The return value indicates whether the parsing should continue, so the function should usually return <code class=highlight><span class=nb>false</span></code>.</p> <details class=example> <summary>Example: report parse errors without exceptions</summary> <p>The example derives from the library's <abbr title="Document Object Model">DOM</abbr> parser and overrides <code>parse_error</code> to print the error instead of throwing. Note the <abbr title="Document Object Model">DOM</abbr> parser is an implementation detail (<code>nlohmann::detail</code>) and may change between releases; see <a href=../../../integration/migration_guide/#do-not-use-the-detail-namespace>Do not use the <code>detail</code> namespace</a>.</p> <div class=highlight><pre><span></span><code><span class=cp>#include</span><span class=w> </span><span class=cpf><iostream></span>
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><nlohmann/json.hpp></span>
|
||||
|
||||
<span class=k>using</span><span class=w> </span><span class=n>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=p>;</span>
|
||||
<span class=k>using</span><span class=w> </span><span class=n>nlohmann</span><span class=o>::</span><span class=n>json</span><span class=p>;</span>
|
||||
|
||||
<span class=c1>// a DOM parser that reports parse errors instead of throwing</span>
|
||||
<span class=k>class</span><span class=w> </span><span class=nc>sax_no_exception</span><span class=w> </span><span class=o>:</span><span class=w> </span><span class=k>public</span><span class=w> </span><span class=n>nlohmann</span><span class=o>::</span><span class=n>detail</span><span class=o>::</span><span class=n>json_sax_dom_parser</span><span class=o><</span><span class=n>json</span><span class=p>,</span><span class=w> </span><span class=n>nlohmann</span><span class=o>::</span><span class=n>detail</span><span class=o>::</span><span class=n>string_input_adapter_type</span><span class=o>></span>
|
||||
@@ -39,7 +39,7 @@
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"parse error at input byte "</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>position</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"</span><span class=se>\n</span><span class=s>"</span>
|
||||
<span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>ex</span><span class=p>.</span><span class=n>what</span><span class=p>()</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"</span><span class=se>\n</span><span class=s>"</span>
|
||||
<span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"last read: </span><span class=se>\"</span><span class=s>"</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>last_token</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"</span><span class=se>\"</span><span class=s>"</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>endl</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=nb>false</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=p>};</span>
|
||||
@@ -54,14 +54,107 @@
|
||||
<span class=w> </span><span class=kt>bool</span><span class=w> </span><span class=n>parse_result</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>sax_parse</span><span class=p>(</span><span class=n>myinput</span><span class=p>,</span><span class=w> </span><span class=o>&</span><span class=n>sax</span><span class=p>);</span>
|
||||
<span class=w> </span><span class=k>if</span><span class=w> </span><span class=p>(</span><span class=o>!</span><span class=n>parse_result</span><span class=p>)</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"parsing unsuccessful!"</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>endl</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"parsing unsuccessful!"</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"parsed value: "</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>result</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>endl</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"parsed value: "</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>result</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
<span class=p>}</span>
|
||||
</code></pre></div> <p>Output:</p> <div class=highlight><pre><span></span><code>parse error at input byte 8
|
||||
[json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal
|
||||
last read: "3,]"
|
||||
parsing unsuccessful!
|
||||
parsed value: [1,2,3]
|
||||
</code></pre></div> </details> <!-- 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 2, 2026 09:32:15 UTC">October 2, 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 © 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.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M162.7 210c-1.8 3.3-25.2 44.4-70.1 123.5-4.9 8.3-10.8 12.5-17.7 12.5H9.8c-7.7 0-12.1-7.5-8.5-14.4l69-121.3q.3 0 0-.3l-43.9-75.6c-4.3-7.8.3-14.1 8.5-14.1H100c7.3 0 13.3 4.1 18 12.2zM382.6 46.1l-144 253v.3L330.2 466c3.9 7.1.2 14.1-8.5 14.1h-65.2c-7.6 0-13.6-4-18-12.2l-92.4-168.5c3.3-5.8 51.5-90.8 144.Line truncated
|
||||
</code></pre></div> </details> <h2 id=where-did-the-error-occur>Where did the error occur?<a class=headerlink href=#where-did-the-error-occur title="Permanent link">¶</a></h2> <p>The message of a <a href=../../../home/exceptions/#jsonexceptionparse_error101><code>parse_error</code></a> for <abbr title="JavaScript Object Notation">JSON</abbr> text contains the line and column of the error:</p> <div class=highlight><pre><span></span><code>[json.exception.parse_error.101] parse error at line 3, column 8: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal
|
||||
</code></pre></div> <p>The exception object itself only stores the <strong>byte index</strong> of the last read character in the member <code>byte</code> (the first byte of the input has index 1). The same index is passed to <code>parse_error</code> in the <a href=../sax_interface/ ><abbr title="Simple API for XML">SAX</abbr> interface</a>. If you need the line and column as numbers, for example to show them in an editor, compute them from the input:</p> <details class=example> <summary>Example: compute line and column of a parse error</summary> <div class=highlight><pre><span></span><code><span class=cp>#include</span><span class=w> </span><span class=cpf><iostream></span>
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><utility></span>
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><nlohmann/json.hpp></span>
|
||||
|
||||
<span class=k>using</span><span class=w> </span><span class=n>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=p>;</span>
|
||||
|
||||
<span class=c1>// line and column (both starting at 1) of a byte index in a text</span>
|
||||
<span class=n>std</span><span class=o>::</span><span class=n>pair</span><span class=o><</span><span class=n>std</span><span class=o>::</span><span class=kt>size_t</span><span class=p>,</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=kt>size_t</span><span class=o>></span><span class=w> </span><span class=n>line_column</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=o>&</span><span class=w> </span><span class=n>input</span><span class=p>,</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=kt>size_t</span><span class=w> </span><span class=kt>byte</span><span class=p>)</span>
|
||||
<span class=p>{</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=kt>size_t</span><span class=w> </span><span class=n>line</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=mi>1</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=kt>size_t</span><span class=w> </span><span class=n>column</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=mi>1</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=k>for</span><span class=w> </span><span class=p>(</span><span class=n>std</span><span class=o>::</span><span class=kt>size_t</span><span class=w> </span><span class=n>i</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=mi>0</span><span class=p>;</span><span class=w> </span><span class=n>i</span><span class=w> </span><span class=o>+</span><span class=w> </span><span class=mi>1</span><span class=w> </span><span class=o><</span><span class=w> </span><span class=kt>byte</span><span class=w> </span><span class=o>&&</span><span class=w> </span><span class=n>i</span><span class=w> </span><span class=o><</span><span class=w> </span><span class=n>input</span><span class=p>.</span><span class=n>size</span><span class=p>();</span><span class=w> </span><span class=o>++</span><span class=n>i</span><span class=p>)</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>if</span><span class=w> </span><span class=p>(</span><span class=n>input</span><span class=p>[</span><span class=n>i</span><span class=p>]</span><span class=w> </span><span class=o>==</span><span class=w> </span><span class=sc>'\n'</span><span class=p>)</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=o>++</span><span class=n>line</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=n>column</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=mi>1</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=k>else</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=o>++</span><span class=n>column</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=p>{</span><span class=n>line</span><span class=p>,</span><span class=w> </span><span class=n>column</span><span class=p>};</span>
|
||||
<span class=p>}</span>
|
||||
|
||||
<span class=kt>int</span><span class=w> </span><span class=n>main</span><span class=p>()</span>
|
||||
<span class=p>{</span>
|
||||
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=w> </span><span class=n>input</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=s>"{</span><span class=se>\n</span><span class=s> </span><span class=se>\"</span><span class=s>a</span><span class=se>\"</span><span class=s>: 1,</span><span class=se>\n</span><span class=s> </span><span class=se>\"</span><span class=s>b</span><span class=se>\"</span><span class=s>: ]</span><span class=se>\n</span><span class=s>}"</span><span class=p>;</span>
|
||||
|
||||
<span class=w> </span><span class=k>try</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>json</span><span class=w> </span><span class=n>j</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>parse</span><span class=p>(</span><span class=n>input</span><span class=p>);</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>j</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=k>catch</span><span class=w> </span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>parse_error</span><span class=o>&</span><span class=w> </span><span class=n>e</span><span class=p>)</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=k>auto</span><span class=w> </span><span class=n>position</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>line_column</span><span class=p>(</span><span class=n>input</span><span class=p>,</span><span class=w> </span><span class=n>e</span><span class=p>.</span><span class=kt>byte</span><span class=p>);</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>e</span><span class=p>.</span><span class=n>what</span><span class=p>()</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"byte "</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>e</span><span class=p>.</span><span class=kt>byte</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>" = line "</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>position</span><span class=p>.</span><span class=n>first</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>", column "</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>position</span><span class=p>.</span><span class=n>second</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=p>}</span>
|
||||
</code></pre></div> <p>Output:</p> <div class=highlight><pre><span></span><code>[json.exception.parse_error.101] parse error at line 3, column 8: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal
|
||||
byte 20 = line 3, column 8
|
||||
</code></pre></div> </details> <p>Columns count bytes, so a line with multi-byte <abbr title="Unicode Transformation Format">UTF</abbr>-8 characters before the error may differ from the column your editor shows.</p> <h3 id=where-is-the-value-that-caused-a-later-error>Where is the value that caused a later error?<a class=headerlink href=#where-is-the-value-that-caused-a-later-error title="Permanent link">¶</a></h3> <p>A <code>parse_error</code> is raised while the text is read. Many mistakes show up later: the text is valid <abbr title="JavaScript Object Notation">JSON</abbr>, but a value has the wrong type when you convert it (<code>type_error.302</code>), or a key is missing (<code>out_of_range.403</code>). The exception then says what is wrong, but not where in the input the value was. Define <a href=../../../api/macros/json_diagnostic_positions/ ><code>JSON_DIAGNOSTIC_POSITIONS</code></a> before including the library to add the byte range of the offending value to such messages (since version 3.12.0), and to query the range of any value with <a href=../../../api/basic_json/start_pos/ ><code>start_pos()</code></a> and <a href=../../../api/basic_json/end_pos/ ><code>end_pos()</code></a>:</p> <details class=example> <summary>Example: locate a value with diagnostic positions</summary> <div class=highlight><pre><span></span><code><span class=cp>#define JSON_DIAGNOSTIC_POSITIONS 1</span>
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><iostream></span>
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><utility></span>
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><nlohmann/json.hpp></span>
|
||||
|
||||
<span class=k>using</span><span class=w> </span><span class=n>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=p>;</span>
|
||||
|
||||
<span class=c1>// line and column (both starting at 1) of a byte index in a text</span>
|
||||
<span class=n>std</span><span class=o>::</span><span class=n>pair</span><span class=o><</span><span class=n>std</span><span class=o>::</span><span class=kt>size_t</span><span class=p>,</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=kt>size_t</span><span class=o>></span><span class=w> </span><span class=n>line_column</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=o>&</span><span class=w> </span><span class=n>input</span><span class=p>,</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=kt>size_t</span><span class=w> </span><span class=kt>byte</span><span class=p>)</span>
|
||||
<span class=p>{</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=kt>size_t</span><span class=w> </span><span class=n>line</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=mi>1</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=kt>size_t</span><span class=w> </span><span class=n>column</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=mi>1</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=k>for</span><span class=w> </span><span class=p>(</span><span class=n>std</span><span class=o>::</span><span class=kt>size_t</span><span class=w> </span><span class=n>i</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=mi>0</span><span class=p>;</span><span class=w> </span><span class=n>i</span><span class=w> </span><span class=o>+</span><span class=w> </span><span class=mi>1</span><span class=w> </span><span class=o><</span><span class=w> </span><span class=kt>byte</span><span class=w> </span><span class=o>&&</span><span class=w> </span><span class=n>i</span><span class=w> </span><span class=o><</span><span class=w> </span><span class=n>input</span><span class=p>.</span><span class=n>size</span><span class=p>();</span><span class=w> </span><span class=o>++</span><span class=n>i</span><span class=p>)</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>if</span><span class=w> </span><span class=p>(</span><span class=n>input</span><span class=p>[</span><span class=n>i</span><span class=p>]</span><span class=w> </span><span class=o>==</span><span class=w> </span><span class=sc>'\n'</span><span class=p>)</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=o>++</span><span class=n>line</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=n>column</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=mi>1</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=k>else</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=o>++</span><span class=n>column</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=k>return</span><span class=w> </span><span class=p>{</span><span class=n>line</span><span class=p>,</span><span class=w> </span><span class=n>column</span><span class=p>};</span>
|
||||
<span class=p>}</span>
|
||||
|
||||
<span class=kt>int</span><span class=w> </span><span class=n>main</span><span class=p>()</span>
|
||||
<span class=p>{</span>
|
||||
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=w> </span><span class=n>input</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=s>"{</span><span class=se>\n</span><span class=s> </span><span class=se>\"</span><span class=s>name</span><span class=se>\"</span><span class=s>: </span><span class=se>\"</span><span class=s>Mary</span><span class=se>\"</span><span class=s>,</span><span class=se>\n</span><span class=s> </span><span class=se>\"</span><span class=s>age</span><span class=se>\"</span><span class=s>: </span><span class=se>\"</span><span class=s>forty-two</span><span class=se>\"\n</span><span class=s>}"</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>json</span><span class=w> </span><span class=n>j</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>parse</span><span class=p>(</span><span class=n>input</span><span class=p>);</span><span class=w> </span><span class=c1>// the input is valid JSON ...</span>
|
||||
|
||||
<span class=w> </span><span class=k>try</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=kt>int</span><span class=w> </span><span class=n>age</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>j</span><span class=p>[</span><span class=s>"age"</span><span class=p>];</span><span class=w> </span><span class=c1>// ... but the value has the wrong type</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>age</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=w> </span><span class=k>catch</span><span class=w> </span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>json</span><span class=o>::</span><span class=n>exception</span><span class=o>&</span><span class=w> </span><span class=n>e</span><span class=p>)</span>
|
||||
<span class=w> </span><span class=p>{</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>e</span><span class=p>.</span><span class=n>what</span><span class=p>()</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
|
||||
<span class=w> </span><span class=c1>// start_pos() is a 0-based index into the input; the helper expects a 1-based byte index</span>
|
||||
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=k>auto</span><span class=w> </span><span class=n>position</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=n>line_column</span><span class=p>(</span><span class=n>input</span><span class=p>,</span><span class=w> </span><span class=n>j</span><span class=p>[</span><span class=s>"age"</span><span class=p>].</span><span class=n>start_pos</span><span class=p>()</span><span class=w> </span><span class=o>+</span><span class=w> </span><span class=mi>1</span><span class=p>);</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>cout</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>"the value starts at line "</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>position</span><span class=p>.</span><span class=n>first</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=s>", column "</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=n>position</span><span class=p>.</span><span class=n>second</span><span class=w> </span><span class=o><<</span><span class=w> </span><span class=sc>'\n'</span><span class=p>;</span>
|
||||
<span class=w> </span><span class=p>}</span>
|
||||
<span class=p>}</span>
|
||||
</code></pre></div> <p>Output:</p> <div class=highlight><pre><span></span><code>[json.exception.type_error.302] (bytes 29-40) type must be number, but is string
|
||||
the value starts at line 3, column 10
|
||||
</code></pre></div> </details> <p>Positions are only available for values created by <a href=../../../api/basic_json/parse/ ><code>parse</code></a>, they are not updated when a value is changed, and the macro makes every value 16 bytes larger on 64-bit platforms, so use it where the cost is acceptable, for example for configuration files. Note that <code>start_pos()</code> is a 0-based index into the input, whereas <code>byte</code> of a <code>parse_error</code> starts at 1.</p> <p>For binary formats such as <abbr title="Concise Binary Object Representation">CBOR</abbr>, there are no lines; <code>byte</code> is the position in the byte sequence. To find out how many bytes a successfully parsed value used, see <a href=../large_and_partial_input/#several-values-in-one-stream>Several values in one stream</a>.</p> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="October 25, 2026 11:07:13 UTC">October 25, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> <div class=md-copyright__highlight> Copyright © 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.2hLine truncated
|
||||
@@ -16,6 +16,10 @@ catch (json::parse_error& ex)
|
||||
|
||||
In case exceptions are undesired or not supported by the environment, there are different ways to proceed:
|
||||
|
||||
Tip
|
||||
|
||||
[Working without exceptions](https://json.nlohmann.me/features/no_exceptions/index.md) also covers accessing values and converting to your own types.
|
||||
|
||||
## Switch off exceptions
|
||||
|
||||
The [`parse()`](https://json.nlohmann.me/api/basic_json/parse/index.md) function accepts a `bool` parameter `allow_exceptions` which controls whether an exception is thrown when a parse error occurs (`true`, default) or whether a discarded value should be returned (`false`).
|
||||
@@ -65,7 +69,7 @@ The example derives from the library's DOM parser and overrides `parse_error` to
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
using nlohmann::json;
|
||||
|
||||
// a DOM parser that reports parse errors instead of throwing
|
||||
class sax_no_exception : public nlohmann::detail::json_sax_dom_parser<json, nlohmann::detail::string_input_adapter_type>
|
||||
@@ -82,7 +86,7 @@ class sax_no_exception : public nlohmann::detail::json_sax_dom_parser<json, nloh
|
||||
std::cout << "parse error at input byte " << position << "\n"
|
||||
<< ex.what() << "\n"
|
||||
<< "last read: \"" << last_token << "\""
|
||||
<< std::endl;
|
||||
<< '\n';
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -97,10 +101,10 @@ int main()
|
||||
bool parse_result = json::sax_parse(myinput, &sax);
|
||||
if (!parse_result)
|
||||
{
|
||||
std::cout << "parsing unsuccessful!" << std::endl;
|
||||
std::cout << "parsing unsuccessful!" << '\n';
|
||||
}
|
||||
|
||||
std::cout << "parsed value: " << result << std::endl;
|
||||
std::cout << "parsed value: " << result << '\n';
|
||||
}
|
||||
```
|
||||
|
||||
@@ -113,3 +117,135 @@ last read: "3,]"
|
||||
parsing unsuccessful!
|
||||
parsed value: [1,2,3]
|
||||
```
|
||||
|
||||
## Where did the error occur?
|
||||
|
||||
The message of a [`parse_error`](https://json.nlohmann.me/home/exceptions/#jsonexceptionparse_error101) for JSON text contains the line and column of the error:
|
||||
|
||||
```
|
||||
[json.exception.parse_error.101] parse error at line 3, column 8: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal
|
||||
```
|
||||
|
||||
The exception object itself only stores the **byte index** of the last read character in the member `byte` (the first byte of the input has index 1). The same index is passed to `parse_error` in the [SAX interface](https://json.nlohmann.me/features/parsing/sax_interface/index.md). If you need the line and column as numbers, for example to show them in an editor, compute them from the input:
|
||||
|
||||
Example: compute line and column of a parse error
|
||||
|
||||
```
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
// line and column (both starting at 1) of a byte index in a text
|
||||
std::pair<std::size_t, std::size_t> line_column(const std::string& input, std::size_t byte)
|
||||
{
|
||||
std::size_t line = 1;
|
||||
std::size_t column = 1;
|
||||
for (std::size_t i = 0; i + 1 < byte && i < input.size(); ++i)
|
||||
{
|
||||
if (input[i] == '\n')
|
||||
{
|
||||
++line;
|
||||
column = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
++column;
|
||||
}
|
||||
}
|
||||
return {line, column};
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const std::string input = "{\n \"a\": 1,\n \"b\": ]\n}";
|
||||
|
||||
try
|
||||
{
|
||||
const json j = json::parse(input);
|
||||
std::cout << j << '\n';
|
||||
}
|
||||
catch (const json::parse_error& e)
|
||||
{
|
||||
const auto position = line_column(input, e.byte);
|
||||
std::cout << e.what() << '\n';
|
||||
std::cout << "byte " << e.byte << " = line " << position.first << ", column " << position.second << '\n';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
[json.exception.parse_error.101] parse error at line 3, column 8: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal
|
||||
byte 20 = line 3, column 8
|
||||
```
|
||||
|
||||
Columns count bytes, so a line with multi-byte UTF-8 characters before the error may differ from the column your editor shows.
|
||||
|
||||
### Where is the value that caused a later error?
|
||||
|
||||
A `parse_error` is raised while the text is read. Many mistakes show up later: the text is valid JSON, but a value has the wrong type when you convert it (`type_error.302`), or a key is missing (`out_of_range.403`). The exception then says what is wrong, but not where in the input the value was. Define [`JSON_DIAGNOSTIC_POSITIONS`](https://json.nlohmann.me/api/macros/json_diagnostic_positions/index.md) before including the library to add the byte range of the offending value to such messages (since version 3.12.0), and to query the range of any value with [`start_pos()`](https://json.nlohmann.me/api/basic_json/start_pos/index.md) and [`end_pos()`](https://json.nlohmann.me/api/basic_json/end_pos/index.md):
|
||||
|
||||
Example: locate a value with diagnostic positions
|
||||
|
||||
```
|
||||
#define JSON_DIAGNOSTIC_POSITIONS 1
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
// line and column (both starting at 1) of a byte index in a text
|
||||
std::pair<std::size_t, std::size_t> line_column(const std::string& input, std::size_t byte)
|
||||
{
|
||||
std::size_t line = 1;
|
||||
std::size_t column = 1;
|
||||
for (std::size_t i = 0; i + 1 < byte && i < input.size(); ++i)
|
||||
{
|
||||
if (input[i] == '\n')
|
||||
{
|
||||
++line;
|
||||
column = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
++column;
|
||||
}
|
||||
}
|
||||
return {line, column};
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const std::string input = "{\n \"name\": \"Mary\",\n \"age\": \"forty-two\"\n}";
|
||||
const json j = json::parse(input); // the input is valid JSON ...
|
||||
|
||||
try
|
||||
{
|
||||
const int age = j["age"]; // ... but the value has the wrong type
|
||||
std::cout << age << '\n';
|
||||
}
|
||||
catch (const json::exception& e)
|
||||
{
|
||||
std::cout << e.what() << '\n';
|
||||
|
||||
// start_pos() is a 0-based index into the input; the helper expects a 1-based byte index
|
||||
const auto position = line_column(input, j["age"].start_pos() + 1);
|
||||
std::cout << "the value starts at line " << position.first << ", column " << position.second << '\n';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
[json.exception.type_error.302] (bytes 29-40) type must be number, but is string
|
||||
the value starts at line 3, column 10
|
||||
```
|
||||
|
||||
Positions are only available for values created by [`parse`](https://json.nlohmann.me/api/basic_json/parse/index.md), they are not updated when a value is changed, and the macro makes every value 16 bytes larger on 64-bit platforms, so use it where the cost is acceptable, for example for configuration files. Note that `start_pos()` is a 0-based index into the input, whereas `byte` of a `parse_error` starts at 1.
|
||||
|
||||
For binary formats such as CBOR, there are no lines; `byte` is the position in the byte sequence. To find out how many bytes a successfully parsed value used, see [Several values in one stream](https://json.nlohmann.me/features/parsing/large_and_partial_input/#several-values-in-one-stream).
|
||||
@@ -86,12 +86,12 @@ was called:
|
||||
#include <iomanip>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
using nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
// a JSON text
|
||||
auto text = R"(
|
||||
const auto* text = R"(
|
||||
{
|
||||
"Image": {
|
||||
"Width": 800,
|
||||
@@ -191,7 +191,7 @@ can detect them while the object is still being read, before that ambiguity ever
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
using json = nlohmann::json;
|
||||
using nlohmann::json;
|
||||
|
||||
json parse_strict(const std::string& input)
|
||||
{
|
||||
|
||||
@@ -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/parsing/parser_callbacks/" rel="canonical"><link href=../parse_exceptions/ rel=prev><link href=../sax_interface/ rel=next><link rel=icon href=../../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>Parser Callbacks - 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=#parser-callbacks 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> Parser Callbacks </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 14Line truncated
|
||||
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=author content="Niels Lohmann"><link href="https://json.nlohmann.me/features/parsing/parser_callbacks/" rel="canonical"><link href=../parse_exceptions/ rel=prev><link href=../sax_interface/ rel=next><link rel=icon href=../../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>Parser Callbacks - 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=#parser-callbacks 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> Parser Callbacks </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 14Line truncated
|
||||
<span class=k>using</span><span class=w> </span><span class=n>parser_callback_t</span><span class=w> </span><span class=o>=</span>
|
||||
<span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>function</span><span class=o><</span><span class=kt>bool</span><span class=p>(</span><span class=kt>int</span><span class=w> </span><span class=n>depth</span><span class=p>,</span><span class=w> </span><span class=n>parse_event_t</span><span class=w> </span><span class=n>event</span><span class=p>,</span><span class=w> </span><span class=n>BasicJsonType</span><span class=o>&</span><span class=w> </span><span class=n>parsed</span><span class=p>)</span><span class=o>></span><span class=p>;</span>
|
||||
</code></pre></div> <h2 id=callback-event-types>Callback event types<a class=headerlink href=#callback-event-types title="Permanent link">¶</a></h2> <p>We distinguish six scenarios (determined by the event type) in which the callback function can be called. The following table describes the values of the parameters <code>depth</code>, <code>event</code>, and <code>parsed</code>.</p> <table> <thead> <tr> <th>parameter <code>event</code></th> <th>description</th> <th>parameter <code>depth</code></th> <th>parameter <code>parsed</code></th> </tr> </thead> <tbody> <tr> <td><code>parse_event_t::object_start</code></td> <td>the parser read <code>{</code> and started to process a <abbr title="JavaScript Object Notation">JSON</abbr> object</td> <td>depth of the parent of the <abbr title="JavaScript Object Notation">JSON</abbr> object</td> <td>a <abbr title="JavaScript Object Notation">JSON</abbr> value with type discarded</td> </tr> <tr> <td><code>parse_event_t::key</code></td> <td>the parser read a key of a value in an object</td> <td>depth of the currently parsed <abbr title="JavaScript Object Notation">JSON</abbr> object</td> <td>a <abbr title="JavaScript Object Notation">JSON</abbr> string containing the key</td> </tr> <tr> <td><code>parse_event_t::object_end</code></td> <td>the parser read <code>}</code> and finished processing a <abbr title="JavaScript Object Notation">JSON</abbr> object</td> <td>depth of the parent of the <abbr title="JavaScript Object Notation">JSON</abbr> object</td> <td>the parsed <abbr title="JavaScript Object Notation">JSON</abbr> object</td> </tr> <tr> <td><code>parse_event_t::array_start</code></td> <td>the parser read <code>[</code> and started to process a <abbr title="JavaScript Object Notation">JSON</abbr> array</td> <td>depth of the parent of the <abbr title="JavaScript Object Notation">JSON</abbr> array</td> <td>a <abbr title="JavaScript Object Notation">JSON</abbr> value with type discarded</td> </tr> <tr> <td><code>parse_event_t::array_end</code></td> <td>the parser read <code>]</code> and finished processing a <abbr title="JavaScript Object Notation">JSON</abbr> array</td> <td>depth of the parent of the <abbr title="JavaScript Object Notation">JSON</abbr> array</td> <td>the parsed <abbr title="JavaScript Object Notation">JSON</abbr> array</td> </tr> <tr> <td><code>parse_event_t::value</code></td> <td>the parser finished reading a <abbr title="JavaScript Object Notation">JSON</abbr> value</td> <td>depth of the value</td> <td>the parsed <abbr title="JavaScript Object Notation">JSON</abbr> value</td> </tr> </tbody> </table> <details class=example> <summary>Example: sequence of callback events</summary> <p>When parsing the following <abbr title="JavaScript Object Notation">JSON</abbr> text,</p> <div class=highlight><pre><span></span><code><span class=p>{</span>
|
||||
@@ -12,12 +12,12 @@
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><iomanip></span>
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><nlohmann/json.hpp></span>
|
||||
|
||||
<span class=k>using</span><span class=w> </span><span class=n>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=p>;</span>
|
||||
<span class=k>using</span><span class=w> </span><span class=n>nlohmann</span><span class=o>::</span><span class=n>json</span><span class=p>;</span>
|
||||
|
||||
<span class=kt>int</span><span class=w> </span><span class=nf>main</span><span class=p>()</span>
|
||||
<span class=p>{</span>
|
||||
<span class=w> </span><span class=c1>// a JSON text</span>
|
||||
<span class=w> </span><span class=k>auto</span><span class=w> </span><span class=n>text</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=sa>R</span><span class=s>"</span><span class=dl>(</span>
|
||||
<span class=w> </span><span class=k>const</span><span class=w> </span><span class=k>auto</span><span class=o>*</span><span class=w> </span><span class=n>text</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=sa>R</span><span class=s>"</span><span class=dl>(</span>
|
||||
<span class=s> {</span>
|
||||
<span class=s> "Image": {</span>
|
||||
<span class=s> "Width": 800,</span>
|
||||
@@ -97,7 +97,7 @@
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><unordered_set></span>
|
||||
<span class=cp>#include</span><span class=w> </span><span class=cpf><vector></span>
|
||||
|
||||
<span class=k>using</span><span class=w> </span><span class=n>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=p>;</span>
|
||||
<span class=k>using</span><span class=w> </span><span class=n>nlohmann</span><span class=o>::</span><span class=n>json</span><span class=p>;</span>
|
||||
|
||||
<span class=n>json</span><span class=w> </span><span class=nf>parse_strict</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>std</span><span class=o>::</span><span class=n>string</span><span class=o>&</span><span class=w> </span><span class=n>input</span><span class=p>)</span>
|
||||
<span class=p>{</span>
|
||||
|
||||
@@ -73,12 +73,12 @@ The example below demonstrates the `parse()` function with and without callback
|
||||
#include <iomanip>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
using nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
// a JSON text
|
||||
auto text = R"(
|
||||
const auto* text = R"(
|
||||
{
|
||||
"Image": {
|
||||
"Width": 800,
|
||||
@@ -172,7 +172,7 @@ Example: reject duplicate object keys
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
using json = nlohmann::json;
|
||||
using nlohmann::json;
|
||||
|
||||
json parse_strict(const std::string& input)
|
||||
{
|
||||
|
||||
@@ -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/parsing/sax_interface/" rel="canonical"><link href=../parser_callbacks/ rel=prev><link href=../untrusted_input/ rel=next><link rel=icon href=../../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>SAX Interface - 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=#sax-interface 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> SAX Interface </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.5Line truncated
|
||||
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=author content="Niels Lohmann"><link href="https://json.nlohmann.me/features/parsing/sax_interface/" rel="canonical"><link href=../parser_callbacks/ rel=prev><link href=../untrusted_input/ rel=next><link rel=icon href=../../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>SAX Interface - 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=#sax-interface 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> SAX Interface </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.5Line truncated
|
||||
|
||||
class sax_t ["json::sax_t"] {
|
||||
<<interface>>
|
||||
|
||||
@@ -26,9 +26,11 @@ several alternatives; see [Parsing and exceptions](parse_exceptions.md) for the
|
||||
[example](parse_exceptions.md#user-defined-sax-interface) that overrides it to print instead of throw.
|
||||
|
||||
If exceptions are unavailable entirely (`-fno-exceptions`, or [`JSON_NOEXCEPTION`](../../api/macros/json_noexception.md)
|
||||
defined), every `#!cpp throw` in the library becomes a call to `std::abort()` -- there is no way to recover from a
|
||||
parse error of untrusted input in that configuration; see
|
||||
[Switch off exceptions](../../home/exceptions.md#switch-off-exceptions) for the details and for overriding this with
|
||||
defined), every `#!cpp throw` in the library becomes a call to `std::abort()`. The alternatives above do not throw, so
|
||||
`parse()` with `allow_exceptions` set to `#!cpp false` (and likewise `accept()` and the `from_*` functions with
|
||||
`allow_exceptions` set to `#!cpp false`) can still reject invalid input in that configuration; a plain `parse()` call
|
||||
aborts on invalid input. See [Working without exceptions](../no_exceptions.md) and
|
||||
[Switch off exceptions](../../home/exceptions.md#switch-off-exceptions) for the details and for overriding the abort with
|
||||
`JSON_THROW_USER`.
|
||||
|
||||
## Nesting depth
|
||||
|
||||
@@ -1 +1 @@
|
||||
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=author content="Niels Lohmann"><link href="https://json.nlohmann.me/features/parsing/untrusted_input/" rel="canonical"><link href=../sax_interface/ rel=prev><link href=../../assertions/ rel=next><link rel=icon href=../../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>Parsing Untrusted Input - 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=#parsing-untrusted-input class=md-skip> Skip to content </a> </div> <div data-md-component=announce> </div> <header class=md-header data-md-component=header> <nav class="md-header__inner md-grid" aria-label=Header> <a href=../../.. title="JSON for Modern C++" class="md-header__button md-logo" aria-label="JSON for Modern C++" data-md-component=logo> <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> Parsing Untrusted Input </span> </div> </div> </div> <form class=md-header__option data-md-component=palette> <input class=md-option data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme=default data-md-color-primary=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 9Line truncated
|
||||
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=author content="Niels Lohmann"><link href="https://json.nlohmann.me/features/parsing/untrusted_input/" rel="canonical"><link href=../sax_interface/ rel=prev><link href=../../assertions/ rel=next><link rel=icon href=../../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>Parsing Untrusted Input - 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=#parsing-untrusted-input class=md-skip> Skip to content </a> </div> <div data-md-component=announce> </div> <header class=md-header data-md-component=header> <nav class="md-header__inner md-grid" aria-label=Header> <a href=../../.. title="JSON for Modern C++" class="md-header__button md-logo" aria-label="JSON for Modern C++" data-md-component=logo> <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> Parsing Untrusted Input </span> </div> </div> </div> <form class=md-header__option data-md-component=palette> <input class=md-option data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme=default data-md-color-primary=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 9Line truncated
|
||||
@@ -12,7 +12,7 @@ By default, [`parse()`](https://json.nlohmann.me/api/basic_json/parse/index.md)
|
||||
- Use [`accept()`](https://json.nlohmann.me/api/basic_json/accept/index.md) to only check whether the input is valid JSON, without building a value.
|
||||
- Implement the [SAX interface](https://json.nlohmann.me/features/parsing/sax_interface/index.md) and override `parse_error()` to react to an error yourself, with the byte position and the exception that would otherwise have been thrown; see the [example](https://json.nlohmann.me/features/parsing/parse_exceptions/#user-defined-sax-interface) that overrides it to print instead of throw.
|
||||
|
||||
If exceptions are unavailable entirely (`-fno-exceptions`, or [`JSON_NOEXCEPTION`](https://json.nlohmann.me/api/macros/json_noexception/index.md) defined), every `throw` in the library becomes a call to `std::abort()` -- there is no way to recover from a parse error of untrusted input in that configuration; see [Switch off exceptions](https://json.nlohmann.me/home/exceptions/#switch-off-exceptions) for the details and for overriding this with `JSON_THROW_USER`.
|
||||
If exceptions are unavailable entirely (`-fno-exceptions`, or [`JSON_NOEXCEPTION`](https://json.nlohmann.me/api/macros/json_noexception/index.md) defined), every `throw` in the library becomes a call to `std::abort()`. The alternatives above do not throw, so `parse()` with `allow_exceptions` set to `false` (and likewise `accept()` and the `from_*` functions with `allow_exceptions` set to `false`) can still reject invalid input in that configuration; a plain `parse()` call aborts on invalid input. See [Working without exceptions](https://json.nlohmann.me/features/no_exceptions/index.md) and [Switch off exceptions](https://json.nlohmann.me/home/exceptions/#switch-off-exceptions) for the details and for overriding the abort with `JSON_THROW_USER`.
|
||||
|
||||
## Nesting depth
|
||||
|
||||
|
||||
Reference in new issue
Block a user