diff --git a/docs/mkdocs/docs/api/basic_json/number_float_t.md b/docs/mkdocs/docs/api/basic_json/number_float_t.md
index 8419a392d..282bb6123 100644
--- a/docs/mkdocs/docs/api/basic_json/number_float_t.md
+++ b/docs/mkdocs/docs/api/basic_json/number_float_t.md
@@ -55,6 +55,10 @@ This implementation does exactly follow this approach, as it uses double precisi
smaller than `-1.79769313486232e+308` and values greater than `1.79769313486232e+308` will be stored as NaN internally
and be serialized to `null`.
+During deserialization (from JSON text or any of the binary formats), a finite number that does not fit into
+`number_float_t` is rejected with [`out_of_range.406`](../../home/exceptions.md#jsonexceptionout_of_range406), for
+example a double-precision number in a binary format when `number_float_t` is `#!cpp float`.
+
### Storage
Floating-point number values are stored directly inside a `basic_json` type.
diff --git a/docs/mkdocs/docs/api/basic_json/number_integer_t.md b/docs/mkdocs/docs/api/basic_json/number_integer_t.md
index d77c6a24d..48d2873ed 100644
--- a/docs/mkdocs/docs/api/basic_json/number_integer_t.md
+++ b/docs/mkdocs/docs/api/basic_json/number_integer_t.md
@@ -47,8 +47,9 @@ With the default values for `NumberIntegerType` (`std::int64_t`), the default va
When the default type is used, the maximal integer number that can be stored is `9223372036854775807` (INT64_MAX) and
the minimal integer number that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers that are out of
-range will yield over/underflow when used in a constructor. During deserialization, too large or small integer numbers
-will automatically be stored as [`number_unsigned_t`](number_unsigned_t.md) or [`number_float_t`](number_float_t.md).
+range will yield over/underflow when used in a constructor. During deserialization (from JSON text or any of the binary
+formats), too large or small integer numbers will automatically be stored as [`number_unsigned_t`](number_unsigned_t.md)
+or [`number_float_t`](number_float_t.md).
[RFC 8259](https://tools.ietf.org/html/rfc8259) further states:
> Note that when such software is used, numbers that are integers and are in the range [-253+1, 253-1] are
diff --git a/docs/mkdocs/docs/api/basic_json/number_unsigned_t.md b/docs/mkdocs/docs/api/basic_json/number_unsigned_t.md
index 774fda638..81cc00f77 100644
--- a/docs/mkdocs/docs/api/basic_json/number_unsigned_t.md
+++ b/docs/mkdocs/docs/api/basic_json/number_unsigned_t.md
@@ -48,8 +48,9 @@ With the default values for `NumberUnsignedType` (`std::uint64_t`), the default
When the default type is used, the maximal integer number that can be stored is `18446744073709551615` (UINT64_MAX) and
the minimal integer number that can be stored is `0`. Integer numbers that are out of range will yield over/underflow
-when used in a constructor. During deserialization, too large or small integer numbers will automatically be stored
-as [`number_integer_t`](number_integer_t.md) or [`number_float_t`](number_float_t.md).
+when used in a constructor. During deserialization (from JSON text or any of the binary formats), too large or small
+integer numbers will automatically be stored as [`number_integer_t`](number_integer_t.md) or
+[`number_float_t`](number_float_t.md).
[RFC 8259](https://tools.ietf.org/html/rfc8259) further states:
> Note that when such software is used, numbers that are integers and are in the range [-253+1, 253-1] are
diff --git a/docs/mkdocs/docs/api/macros/index.md b/docs/mkdocs/docs/api/macros/index.md
index 872d6cb8c..ffeb9639c 100644
--- a/docs/mkdocs/docs/api/macros/index.md
+++ b/docs/mkdocs/docs/api/macros/index.md
@@ -58,6 +58,8 @@ header. See also the [macro overview page](../../features/macros.md).
- [**JSON_DISABLE_ENUM_SERIALIZATION**](json_disable_enum_serialization.md) - switch off default serialization/deserialization functions for enums
- [**JSON_DISABLE_TUPLE_REFERENCE_CONVERSION**](json_disable_tuple_reference_conversion.md) - switch off conversion from a one-element tuple of a JSON reference
- [**JSON_USE_IMPLICIT_CONVERSIONS**](json_use_implicit_conversions.md) - control implicit conversions
+- [**JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS**](json_use_objects_for_enum_keyed_maps.md) - opt in to storing maps with enum
+ keys as objects
## Comparison behavior
diff --git a/docs/mkdocs/docs/api/macros/json_use_objects_for_enum_keyed_maps.md b/docs/mkdocs/docs/api/macros/json_use_objects_for_enum_keyed_maps.md
new file mode 100644
index 000000000..a84d83129
--- /dev/null
+++ b/docs/mkdocs/docs/api/macros/json_use_objects_for_enum_keyed_maps.md
@@ -0,0 +1,139 @@
+# JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS
+
+```cpp
+#define JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS /* value */
+```
+
+When defined to `1`, maps whose keys are enums (such as `std::map` or `std::unordered_map`) are stored as
+JSON objects, using the enum's own conversion for the keys. By default, they are stored as arrays of `[key, value]`
+pairs.
+
+## Default definition
+
+The default value is `0` (disabled — existing behavior is preserved).
+
+```cpp
+#define JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS 0
+```
+
+## Notes
+
+!!! note "Background"
+
+ JSON object keys are strings, so a map is only stored as an object if its keys can be converted to a string type.
+ Enums are not, even if [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md) maps them to strings, so a
+ map with enum keys becomes an array of `[key, value]` pairs:
+
+ ```json
+ [["stopped", "aa"], ["completed", "bb"]]
+ ```
+
+ With this macro, the same map becomes an object
+ (see [#4378](https://github.com/nlohmann/json/issues/4378)):
+
+ ```json
+ {"completed": "bb", "stopped": "aa"}
+ ```
+
+!!! note "Maps with non-unique keys"
+
+ Maps that allow duplicate keys, such as `std::multimap` or `std::unordered_multimap`, are not affected
+ by the macro and are still stored as arrays of `[key, value]` pairs, as an object cannot hold duplicate keys.
+
+!!! note "Reading"
+
+ Reading is not affected by the macro: a map with enum keys can always be read from both an array of pairs and an
+ object. For the latter, each key is converted to the enum with its `from_json` function, e.g., the one defined by
+ [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md). Data written without the macro can therefore
+ still be read after enabling it.
+
+!!! warning "Keys must serialize to distinct strings"
+
+ Each key is converted with the enum's `to_json` function. If a key is not converted to a string (for instance, an
+ enum without [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md), which is stored as an integer, or an
+ enumerator mapped to `nullptr`), [`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) is thrown.
+ If two keys are converted to the same string (for instance, because
+ [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md) maps an unlisted enumerator to the first entry),
+ [`type_error.318`](../../home/exceptions.md#jsonexceptiontype_error318) is thrown. In both cases, the target value
+ is not changed.
+
+!!! warning "Opt-in only"
+
+ This macro must be defined **before** including ``. Defining it after the include has no effect.
+
+!!! note "ABI compatibility"
+
+ The value of this macro is encoded in the [namespace](../../features/namespace.md) (tag `_ekmo`), resulting in
+ distinct symbol names. Translation units compiled with and without it can therefore be linked into the same program
+ without One Definition Rule (ODR) violations, but they cannot exchange instances of library types.
+
+## Examples
+
+??? example "Default behavior (macro not defined)"
+
+ Without the macro, a map with enum keys is stored as an array of pairs:
+
+ ```cpp
+ #include