This commit is contained in:
nlohmann committed 2026-10-29 06:46:38 +00:00
1 parent 40c9f42917
commit cf84df303b
14 files changed
+463 -412

No files matched your search

+3
View File
@@ -64,6 +64,9 @@ bool parse_error(std::size_t position, const std::string& last_token, const json
The return value of each function determines whether parsing should proceed.
Object keys are passed to `key` decoded and validated: escape sequences are already resolved, so different spellings of
the same name yield the same string. See [`key`](../../api/json_sax/key.md#notes) for the exact guarantees.
## Stepping through the events
The events for a small input, step by step, and what two different handlers do with them. Press *Play* or step with *Next*:
+2 -2
View File
@@ -49,10 +49,10 @@ class sax_t ["json::sax_t"] {
<span class=c1>// called when a parse error occurs; byte position, the last token, and an exception is passed</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=n>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>&amp;</span><span class=w> </span><span class=n>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>&amp;</span><span class=w> </span><span class=n>ex</span><span class=p>);</span>
</code></pre></div> <p>The return value of each function determines whether parsing should proceed.</p> <h2 id=stepping-through-the-events>Stepping through the events<a class=headerlink href=#stepping-through-the-events title="Permanent link">&para;</a></h2> <p>The events for a small input, step by step, and what two different handlers do with them. Press <em>Play</em> or step with <em>Next</em>:</p> <div class="nj-sax nj-fig" id=sax-event-stepper data-nj-sax role=group aria-label='SAX events for the input {"a":[1,true],"b":"x"}, and the state of a handler after each event'> <div class="nj-sax__lane nj-sax__lane--text"><p class=nj-sax__h>input</p><p class=nj-sax__text><code class=nj-sax__src>{"a":[1,true],"b":"x"}</code></p></div> <div class="nj-sax__lane nj-sax__lane--events"><p class=nj-sax__h>events, in the order the parser calls them</p><ol class=nj-sax__events> <li class="nj-sax-ev nj-sax-ev--os"><code>start_object(-1)</code></li> <li class="nj-sax-ev nj-sax-ev--k"><code>key("a")</code></li> <li class="nj-sax-ev nj-sax-ev--as"><code>start_array(-1)</code></li> <li class="nj-sax-ev nj-sax-ev--v"><code>number_unsigned(1)</code></li> <li class="nj-sax-ev nj-sax-ev--v"><code>boolean(true)</code></li> <li class="nj-sax-ev nj-sax-ev--ae"><code>end_array()</code></li> <li class="nj-sax-ev nj-sax-ev--k"><code>key("b")</code></li> <li class="nj-sax-ev nj-sax-ev--v"><code>string("x")</code></li> <li class="nj-sax-ev nj-sax-ev--oe"><code>end_object()</code></li> </ol></div> <div class="nj-sax__lane nj-sax__lane--state"><p class=nj-sax__h>handler: build a value tree, as <code>parse</code> does</p><div class=nj-sax__state><pre class=nj-sax__tree><code>{
</code></pre></div> <p>The return value of each function determines whether parsing should proceed.</p> <p>Object keys are passed to <code>key</code> decoded and validated: escape sequences are already resolved, so different spellings of the same name yield the same string. See <a href=../../../api/json_sax/key/#notes><code>key</code></a> for the exact guarantees.</p> <h2 id=stepping-through-the-events>Stepping through the events<a class=headerlink href=#stepping-through-the-events title="Permanent link">&para;</a></h2> <p>The events for a small input, step by step, and what two different handlers do with them. Press <em>Play</em> or step with <em>Next</em>:</p> <div class="nj-sax nj-fig" id=sax-event-stepper data-nj-sax role=group aria-label='SAX events for the input {"a":[1,true],"b":"x"}, and the state of a handler after each event'> <div class="nj-sax__lane nj-sax__lane--text"><p class=nj-sax__h>input</p><p class=nj-sax__text><code class=nj-sax__src>{"a":[1,true],"b":"x"}</code></p></div> <div class="nj-sax__lane nj-sax__lane--events"><p class=nj-sax__h>events, in the order the parser calls them</p><ol class=nj-sax__events> <li class="nj-sax-ev nj-sax-ev--os"><code>start_object(-1)</code></li> <li class="nj-sax-ev nj-sax-ev--k"><code>key("a")</code></li> <li class="nj-sax-ev nj-sax-ev--as"><code>start_array(-1)</code></li> <li class="nj-sax-ev nj-sax-ev--v"><code>number_unsigned(1)</code></li> <li class="nj-sax-ev nj-sax-ev--v"><code>boolean(true)</code></li> <li class="nj-sax-ev nj-sax-ev--ae"><code>end_array()</code></li> <li class="nj-sax-ev nj-sax-ev--k"><code>key("b")</code></li> <li class="nj-sax-ev nj-sax-ev--v"><code>string("x")</code></li> <li class="nj-sax-ev nj-sax-ev--oe"><code>end_object()</code></li> </ol></div> <div class="nj-sax__lane nj-sax__lane--state"><p class=nj-sax__h>handler: build a value tree, as <code>parse</code> does</p><div class=nj-sax__state><pre class=nj-sax__tree><code>{
"a": [
1,
true
],
"b": "x"
}</code></pre><p class=nj-sax__note>After <code>end_object()</code> the tree is complete and no container is open. The number of elements is passed as -1: the parser does not know it in advance.</p></div></div> </div> <p class=nj-caption>The three lanes show the input consumed so far, the events called so far, and the state of the selected handler (<em>build a tree</em> or <em>keep only /b</em>). Check <em>return false at this event</em> to stop the parse at the current event and see which events are no longer called.</p> <p>To implement your own <abbr title="Simple API for XML">SAX</abbr> handler, proceed as follows:</p> <ol> <li>Implement the <abbr title="Simple API for XML">SAX</abbr> interface in a class. You can use class <code>nlohmann::json_sax&lt;json&gt;</code> as base class, but you can also use any class where the functions described above are implemented and public.</li> <li>Create an object of your <abbr title="Simple API for XML">SAX</abbr> interface class, e.g. <code>my_sax</code>.</li> <li>Call <code class=highlight><span class=kt>bool</span><span class=w> </span><span class=nf>json::sax_parse</span><span class=p>(</span><span class=n>input</span><span class=p>,</span><span class=w> </span><span class=o>&amp;</span><span class=n>my_sax</span><span class=p>);</span></code> where the first parameter can be any input like a string or an input stream and the second parameter is a pointer to your <abbr title="Simple API for XML">SAX</abbr> interface.</li> </ol> <p>Note the <code>sax_parse</code> function only returns a <code class=highlight><span class=kt>bool</span></code> indicating the result of the last executed <abbr title="Simple API for XML">SAX</abbr> event. It does not return <code>json</code> value - it is up to you to decide what to do with the <abbr title="Simple API for XML">SAX</abbr> events. Furthermore, no exceptions are thrown in case of a parse error - it is up to you what to do with the exception object passed to your <code>parse_error</code> implementation. Internally, the <abbr title="Simple API for XML">SAX</abbr> interface is used for the <abbr title="Document Object Model">DOM</abbr> parser (class <code>json_sax_dom_parser</code>) as well as the acceptor (<code>json_sax_acceptor</code>), see file <code>json_sax.hpp</code>.</p> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li><a href=../../../api/json_sax/ ><code>json_sax</code></a> - documentation of the <abbr title="Simple API for XML">SAX</abbr> interface</li> <li><a href=../../../api/basic_json/sax_parse/ ><code>sax_parse</code></a> - <abbr title="Simple API for XML">SAX</abbr> parser</li> <li><a href=../ >Parsing</a> - overview of the parsing functions</li> <li><a href=../parse_exceptions/ >Parsing and Exceptions</a> - handling parse errors and locating them in the input</li> <li><a href=../../../api/basic_json/parse/ ><code>parse</code></a> - deserialize from a compatible input</li> <li><a href=../../binary_formats/ >Binary Formats</a> - <abbr title="Concise Binary Object Representation">CBOR</abbr>, MessagePack, <abbr title="Binary JSON">BSON</abbr>, and other formats</li> </ul> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="October 27, 2026 06:41:42 UTC">October 27, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <nav class="md-footer__inner md-grid" aria-label=Footer> <a href=../parser_callbacks/ class="md-footer__link md-footer__link--prev" aria-label="Previous: Parser Callbacks"> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbLine truncated
}</code></pre><p class=nj-sax__note>After <code>end_object()</code> the tree is complete and no container is open. The number of elements is passed as -1: the parser does not know it in advance.</p></div></div> </div> <p class=nj-caption>The three lanes show the input consumed so far, the events called so far, and the state of the selected handler (<em>build a tree</em> or <em>keep only /b</em>). Check <em>return false at this event</em> to stop the parse at the current event and see which events are no longer called.</p> <p>To implement your own <abbr title="Simple API for XML">SAX</abbr> handler, proceed as follows:</p> <ol> <li>Implement the <abbr title="Simple API for XML">SAX</abbr> interface in a class. You can use class <code>nlohmann::json_sax&lt;json&gt;</code> as base class, but you can also use any class where the functions described above are implemented and public.</li> <li>Create an object of your <abbr title="Simple API for XML">SAX</abbr> interface class, e.g. <code>my_sax</code>.</li> <li>Call <code class=highlight><span class=kt>bool</span><span class=w> </span><span class=nf>json::sax_parse</span><span class=p>(</span><span class=n>input</span><span class=p>,</span><span class=w> </span><span class=o>&amp;</span><span class=n>my_sax</span><span class=p>);</span></code> where the first parameter can be any input like a string or an input stream and the second parameter is a pointer to your <abbr title="Simple API for XML">SAX</abbr> interface.</li> </ol> <p>Note the <code>sax_parse</code> function only returns a <code class=highlight><span class=kt>bool</span></code> indicating the result of the last executed <abbr title="Simple API for XML">SAX</abbr> event. It does not return <code>json</code> value - it is up to you to decide what to do with the <abbr title="Simple API for XML">SAX</abbr> events. Furthermore, no exceptions are thrown in case of a parse error - it is up to you what to do with the exception object passed to your <code>parse_error</code> implementation. Internally, the <abbr title="Simple API for XML">SAX</abbr> interface is used for the <abbr title="Document Object Model">DOM</abbr> parser (class <code>json_sax_dom_parser</code>) as well as the acceptor (<code>json_sax_acceptor</code>), see file <code>json_sax.hpp</code>.</p> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li><a href=../../../api/json_sax/ ><code>json_sax</code></a> - documentation of the <abbr title="Simple API for XML">SAX</abbr> interface</li> <li><a href=../../../api/basic_json/sax_parse/ ><code>sax_parse</code></a> - <abbr title="Simple API for XML">SAX</abbr> parser</li> <li><a href=../ >Parsing</a> - overview of the parsing functions</li> <li><a href=../parse_exceptions/ >Parsing and Exceptions</a> - handling parse errors and locating them in the input</li> <li><a href=../../../api/basic_json/parse/ ><code>parse</code></a> - deserialize from a compatible input</li> <li><a href=../../binary_formats/ >Binary Formats</a> - <abbr title="Concise Binary Object Representation">CBOR</abbr>, MessagePack, <abbr title="Binary JSON">BSON</abbr>, and other formats</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 29, 2026 06:37:33 UTC">October 29, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <nav class="md-footer__inner md-grid" aria-label=Footer> <a href=../parser_callbacks/ class="md-footer__link md-footer__link--prev" aria-label="Previous: Parser Callbacks"> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbLine truncated
+2
View File
@@ -64,6 +64,8 @@ bool parse_error(std::size_t position, const std::string& last_token, const json
The return value of each function determines whether parsing should proceed.
Object keys are passed to `key` decoded and validated: escape sequences are already resolved, so different spellings of the same name yield the same string. See [`key`](https://json.nlohmann.me/api/json_sax/key/#notes) for the exact guarantees.
## Stepping through the events
The events for a small input, step by step, and what two different handlers do with them. Press *Play* or step with *Next*: