diff --git a/api/basic_json/parser_callback_t.md b/api/basic_json/parser_callback_t.md
index d0c6258df..2b5c01834 100644
--- a/api/basic_json/parser_callback_t.md
+++ b/api/basic_json/parser_callback_t.md
@@ -102,6 +102,15 @@ called:
Whether the JSON value which called the function during parsing should be kept (`#!cpp true`) or not (`#!cpp false`). In
the latter case, it is skipped completely, or replaced by `null` if it is the top-level value.
+## Notes
+
+For a `parse_event_t::key` event, `parsed` holds the decoded object name, with the same guarantees as the `val`
+parameter of [`json_sax::key`](../json_sax/key.md#notes): all escape sequences are decoded and `\uXXXX` escapes are
+stored as UTF-8, so different spellings of the same name yield identical strings; the name is validated completely
+before the callback is called, so a name with an invalid escape sequence or ill-formed UTF-8 causes a parse error and
+no `key` event; no Unicode normalization or case conversion is applied; and a name that occurs several times in the
+same object yields one `key` event per occurrence.
+
## Examples
??? example "Example: skip an object key while parsing"
diff --git a/api/basic_json/parser_callback_t/index.html b/api/basic_json/parser_callback_t/index.html
index b41a089fc..7e0f11711 100644
--- a/api/basic_json/parser_callback_t/index.html
+++ b/api/basic_json/parser_callback_t/index.html
@@ -1,7 +1,7 @@
-
With a parser callback function, the result of parsing a JSON text can be influenced. When passed to parse, it is called on certain events (passed as parse_event_t via parameter event) with a set recursion depth depth and context JSON value parsed. The return value of the callback function is a boolean indicating whether the element that emitted the callback shall be kept or not.
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 depth, event, and parsed.
parameter event
description
parameter depth
parameter parsed
parse_event_t::object_start
the parser read { and started to process a JSON object
depth of the parent of the JSON object
a JSON value with type discarded
parse_event_t::key
the parser read a key of a value in an object
depth of the currently parsed JSON object
a JSON string containing the key
parse_event_t::object_end
the parser read } and finished processing a JSON object
depth of the parent of the JSON object
the parsed JSON object
parse_event_t::array_start
the parser read [ and started to process a JSON array
depth of the parent of the JSON array
a JSON value with type discarded
parse_event_t::array_end
the parser read ] and finished processing a JSON array
depth of the parent of the JSON array
the parsed JSON array
parse_event_t::value
the parser finished reading a JSON value
depth of the value
the parsed JSON value
Parse events for a small JSON text: each coloured dot marks the position at which the parser calls the callback, and the legend on the right names the event per colour.
Discarding a value (i.e., returning false) has different effects depending on the context in which function was called:
Discarded values in structured types are skipped. That is, the parser will behave as if the discarded value was never read. This holds for every value type and for both kinds of parent: a discarded element is removed from the surrounding array, and a discarded member is removed from the surrounding object together with its key.
Arrays and objects can be discarded either at their parse_event_t::array_start/parse_event_t::object_start event or at their parse_event_t::array_end/parse_event_t::object_end event, and both remove the whole value. Discarding it at the start event also means the callback is called neither for the content of the value nor for its matching end event.
Discarding a parse_event_t::key event discards the whole object member. The callback is still called for the associated value, but its return value has no further effect.
In case a value outside a structured type is skipped, it is replaced with null. This case happens if the top-level element is skipped.
Whether the JSON value which called the function during parsing should be kept (true) or not (false). In the latter case, it is skipped completely, or replaced by null if it is the top-level value.
The example below demonstrates the parse() function with and without callback function.
#include<iostream>
+
With a parser callback function, the result of parsing a JSON text can be influenced. When passed to parse, it is called on certain events (passed as parse_event_t via parameter event) with a set recursion depth depth and context JSON value parsed. The return value of the callback function is a boolean indicating whether the element that emitted the callback shall be kept or not.
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 depth, event, and parsed.
parameter event
description
parameter depth
parameter parsed
parse_event_t::object_start
the parser read { and started to process a JSON object
depth of the parent of the JSON object
a JSON value with type discarded
parse_event_t::key
the parser read a key of a value in an object
depth of the currently parsed JSON object
a JSON string containing the key
parse_event_t::object_end
the parser read } and finished processing a JSON object
depth of the parent of the JSON object
the parsed JSON object
parse_event_t::array_start
the parser read [ and started to process a JSON array
depth of the parent of the JSON array
a JSON value with type discarded
parse_event_t::array_end
the parser read ] and finished processing a JSON array
depth of the parent of the JSON array
the parsed JSON array
parse_event_t::value
the parser finished reading a JSON value
depth of the value
the parsed JSON value
Parse events for a small JSON text: each coloured dot marks the position at which the parser calls the callback, and the legend on the right names the event per colour.
Discarding a value (i.e., returning false) has different effects depending on the context in which function was called:
Discarded values in structured types are skipped. That is, the parser will behave as if the discarded value was never read. This holds for every value type and for both kinds of parent: a discarded element is removed from the surrounding array, and a discarded member is removed from the surrounding object together with its key.
Arrays and objects can be discarded either at their parse_event_t::array_start/parse_event_t::object_start event or at their parse_event_t::array_end/parse_event_t::object_end event, and both remove the whole value. Discarding it at the start event also means the callback is called neither for the content of the value nor for its matching end event.
Discarding a parse_event_t::key event discards the whole object member. The callback is still called for the associated value, but its return value has no further effect.
In case a value outside a structured type is skipped, it is replaced with null. This case happens if the top-level element is skipped.
Whether the JSON value which called the function during parsing should be kept (true) or not (false). In the latter case, it is skipped completely, or replaced by null if it is the top-level value.
For a parse_event_t::key event, parsed holds the decoded object name, with the same guarantees as the val parameter of json_sax::key: all escape sequences are decoded and \uXXXX escapes are stored as UTF-8, so different spellings of the same name yield identical strings; the name is validated completely before the callback is called, so a name with an invalid escape sequence or ill-formed UTF-8 causes a parse error and no key event; no Unicode normalization or case conversion is applied; and a name that occurs several times in the same object yields one key event per occurrence.
Fixed in version 3.13.0 unreleased to also remove discarded values from a parent object; before, discarding an array or a value stored under an object key left a discarded member behind, which made the parse result serialize to invalid JSON.
Fixed in version 3.13.0 unreleased so that discarding an array or object at its start event also hides its content from the callback, as documented above; before, the callback was still called for the content, and the key of every member of a discarded object was kept in memory until the parse ended.
Fixed in version 3.13.0 unreleased to also remove discarded values from a parent object; before, discarding an array or a value stored under an object key left a discarded member behind, which made the parse result serialize to invalid JSON.
Fixed in version 3.13.0 unreleased so that discarding an array or object at its start event also hides its content from the callback, as documented above; before, the callback was still called for the content, and the key of every member of a discarded object was kept in memory until the parse ended.
\ No newline at end of file
diff --git a/api/basic_json/parser_callback_t/index.md b/api/basic_json/parser_callback_t/index.md
index 8e11d0eea..e510419fb 100644
--- a/api/basic_json/parser_callback_t/index.md
+++ b/api/basic_json/parser_callback_t/index.md
@@ -40,6 +40,10 @@ Discarding a value (i.e., returning `false`) has different effects depending on
Whether the JSON value which called the function during parsing should be kept (`true`) or not (`false`). In the latter case, it is skipped completely, or replaced by `null` if it is the top-level value.
+## Notes
+
+For a `parse_event_t::key` event, `parsed` holds the decoded object name, with the same guarantees as the `val` parameter of [`json_sax::key`](https://json.nlohmann.me/api/json_sax/key/#notes): all escape sequences are decoded and `\uXXXX` escapes are stored as UTF-8, so different spellings of the same name yield identical strings; the name is validated completely before the callback is called, so a name with an invalid escape sequence or ill-formed UTF-8 causes a parse error and no `key` event; no Unicode normalization or case conversion is applied; and a name that occurs several times in the same object yields one `key` event per occurrence.
+
## Examples
Example: skip an object key while parsing
diff --git a/api/json_sax/key.md b/api/json_sax/key.md
index 6614eab9b..0a11d6e16 100644
--- a/api/json_sax/key.md
+++ b/api/json_sax/key.md
@@ -19,6 +19,23 @@ Whether parsing should proceed.
It is safe to move the passed object key value.
+When parsing JSON text, `val` is the decoded object name, not its spelling in the input:
+
+- All escape sequences (`\"`, `\\`, `\/`, `\b`, `\f`, `\n`, `\r`, `\t`, `\uXXXX`, and surrogate pairs) are
+ decoded, and `\uXXXX` escapes are stored as UTF-8. Different spellings of the same name, such as `#!json "/"`
+ and `#!json "\/"`, or `#!json "\u00e9"` and `#!json "\u00E9"`, yield identical strings. An escaped `\u0000` yields
+ an embedded NUL byte.
+- The name is scanned and validated completely before `key` is called. If it contains an invalid escape sequence, an
+ unpaired surrogate, a control character, or ill-formed UTF-8, the parse fails with a
+ [`parse_error`](../../home/exceptions.md#parse-errors), and `key` is not called for it.
+- No Unicode normalization or case conversion is applied: names that differ in any byte are different strings.
+- `key` is called before the following `:` is read, so a parse error may still follow for the same member.
+- A name that occurs several times in the same object is passed once per occurrence.
+
+For the binary formats, object keys contain no escape sequences. For CBOR, MessagePack, UBJSON, and BSON, `val` holds
+the bytes stored in the input, and [`sax_parse`](../basic_json/sax_parse.md) passes them unchanged, without checking them
+for valid UTF-8. BON8 encodes characters itself, so an ill-formed name is a parse error and `key` is not called for it.
+
## Examples
??? example
@@ -213,3 +230,7 @@ It is safe to move the passed object key value.
## Version history
- Added in version 3.2.0.
+- The behavior described in the notes above (decoded names, validation before `key` is called, no normalization, `key`
+ before the `:` check, one call per duplicate, bytes of binary formats passed unchanged) is the same in all versions
+ from 3.2.0 on, and for the `key` event of a [parser callback](../basic_json/parser_callback_t.md) from 3.0.0 on. BSON
+ is only supported from version 3.4.0, and BON8 only from version 3.13.0.
diff --git a/api/json_sax/key/index.html b/api/json_sax/key/index.html
index 723cefda4..313bf530c 100644
--- a/api/json_sax/key/index.html
+++ b/api/json_sax/key/index.html
@@ -1,5 +1,5 @@
key - JSON for Modern C++
When parsing JSON text, val is the decoded object name, not its spelling in the input:
All escape sequences (\", \\, \/, \b, \f, \n, \r, \t, \uXXXX, and surrogate pairs) are decoded, and \uXXXX escapes are stored as UTF-8. Different spellings of the same name, such as "/" and "\/", or "\u00e9" and "\u00E9", yield identical strings. An escaped \u0000 yields an embedded NUL byte.
The name is scanned and validated completely before key is called. If it contains an invalid escape sequence, an unpaired surrogate, a control character, or ill-formed UTF-8, the parse fails with a parse_error, and key is not called for it.
No Unicode normalization or case conversion is applied: names that differ in any byte are different strings.
key is called before the following : is read, so a parse error may still follow for the same member.
A name that occurs several times in the same object is passed once per occurrence.
For the binary formats, object keys contain no escape sequences. For CBOR, MessagePack, UBJSON, and BSON, val holds the bytes stored in the input, and sax_parse passes them unchanged, without checking them for valid UTF-8. BON8 encodes characters itself, so an ill-formed name is a parse error and key is not called for it.
The behavior described in the notes above (decoded names, validation before key is called, no normalization, key before the : check, one call per duplicate, bytes of binary formats passed unchanged) is the same in all versions from 3.2.0 on, and for the key event of a parser callback from 3.0.0 on. BSON is only supported from version 3.4.0, and BON8 only from version 3.13.0 unreleased.