Restructure inline namespace and allow version component to be disabled (#3683)

diff --git a/docs/docset/docSet.sql b/docs/docset/docSet.sql
index 8a4272a..f97647d 100644
--- a/docs/docset/docSet.sql
+++ b/docs/docset/docSet.sql
@@ -183,6 +183,7 @@
 INSERT INTO searchIndex(name, type, path) VALUES ('JSON Merge Patch', 'Guide', 'features/merge_patch/index.html');
 INSERT INTO searchIndex(name, type, path) VALUES ('JSON Patch and Diff', 'Guide', 'features/json_patch/index.html');
 INSERT INTO searchIndex(name, type, path) VALUES ('JSON Pointer', 'Guide', 'features/json_pointer/index.html');
+INSERT INTO searchIndex(name, type, path) VALUES ('nlohmann Namespace', 'Guide', 'features/namespace/index.html');
 INSERT INTO searchIndex(name, type, path) VALUES ('Types', 'Guide', 'features/types/index.html');
 INSERT INTO searchIndex(name, type, path) VALUES ('Types: Number Handling', 'Guide', 'features/types/number_handling/index.html');
 INSERT INTO searchIndex(name, type, path) VALUES ('Object Order', 'Guide', 'features/object_order/index.html');
@@ -225,6 +226,7 @@
 INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_NAMESPACE', 'Macro', 'api/macros/nlohmann_json_namespace/index.html');
 INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_NAMESPACE_BEGIN', 'Macro', 'api/macros/nlohmann_json_namespace_begin/index.html');
 INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_NAMESPACE_END', 'Macro', 'api/macros/nlohmann_json_namespace_begin/index.html');
+INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_NAMESPACE_NO_VERSION', 'Macro', 'api/macros/nlohmann_json_namespace_no_version/index.html');
 INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_SERIALIZE_ENUM', 'Macro', 'api/macros/nlohmann_json_serialize_enum/index.html');
 INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_VERSION_MAJOR', 'Macro', 'api/macros/nlohmann_json_version_major/index.html');
 INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_VERSION_MINOR', 'Macro', 'api/macros/nlohmann_json_version_major/index.html');
diff --git a/docs/examples/nlohmann_json_namespace.output b/docs/examples/nlohmann_json_namespace.output
index d5a8b59..e943d34 100644
--- a/docs/examples/nlohmann_json_namespace.output
+++ b/docs/examples/nlohmann_json_namespace.output
@@ -1 +1 @@
-nlohmann::json_v3_11_1
+nlohmann::json_abi_v3_11_1
diff --git a/docs/examples/nlohmann_json_namespace_no_version.cpp b/docs/examples/nlohmann_json_namespace_no_version.cpp
new file mode 100644
index 0000000..97948dd
--- /dev/null
+++ b/docs/examples/nlohmann_json_namespace_no_version.cpp
@@ -0,0 +1,13 @@
+#include <iostream>
+
+#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 1
+#include <nlohmann/json.hpp>
+
+// macro needed to output the NLOHMANN_JSON_NAMESPACE as string literal
+#define Q(x) #x
+#define QUOTE(x) Q(x)
+
+int main()
+{
+    std::cout << QUOTE(NLOHMANN_JSON_NAMESPACE) << std::endl;
+}
diff --git a/docs/examples/nlohmann_json_namespace_no_version.output b/docs/examples/nlohmann_json_namespace_no_version.output
new file mode 100644
index 0000000..1c8f313
--- /dev/null
+++ b/docs/examples/nlohmann_json_namespace_no_version.output
@@ -0,0 +1 @@
+nlohmann::json_abi
diff --git a/docs/mkdocs/docs/api/macros/index.md b/docs/mkdocs/docs/api/macros/index.md
index 8e118b0..099dfa6 100644
--- a/docs/mkdocs/docs/api/macros/index.md
+++ b/docs/mkdocs/docs/api/macros/index.md
@@ -32,7 +32,10 @@
 ## Library namespace
 
 - [**NLOHMANN_JSON_NAMESPACE**](nlohmann_json_namespace.md) - full name of the `nlohmann` namespace
-- [**NLOHMANN_JSON_NAMESPACE_BEGIN**<br>**NLOHMANN_JSON_NAMESPACE_END**](nlohmann_json_namespace_begin.md) - open and close the library namespace
+- [**NLOHMANN_JSON_NAMESPACE_BEGIN**<br>**NLOHMANN_JSON_NAMESPACE_END**](nlohmann_json_namespace_begin.md) - open and
+  close the library namespace
+- [**NLOHMANN_JSON_NAMESPACE_NO_VERSION**](nlohmann_json_namespace_no_version.md) - disable the version component of
+  the inline namespace
 
 ## Type conversions
 
diff --git a/docs/mkdocs/docs/api/macros/nlohmann_json_namespace.md b/docs/mkdocs/docs/api/macros/nlohmann_json_namespace.md
index b44538e..5c54dba 100644
--- a/docs/mkdocs/docs/api/macros/nlohmann_json_namespace.md
+++ b/docs/mkdocs/docs/api/macros/nlohmann_json_namespace.md
@@ -1,19 +1,18 @@
 # NLOHMANN_JSON_NAMESPACE
 
 ```cpp
-#define NLOHMANN_JSON_NAMESPACE
+#define NLOHMANN_JSON_NAMESPACE /* value */
 ```
 
-This macro evaluates to the full name of the `nlohmann` namespace, including  the name of a versioned and ABI-tagged
-inline namespace. Use this macro to unambiguously refer to the `nlohmann` namespace.
+This macro evaluates to the full name of the `nlohmann` namespace.
 
 ## Default definition
 
-The default value consists of a prefix, a version string, and optional ABI tags depending on whether ABI-affecting
-macros are defined (e.g., [`JSON_DIAGNOSTICS`](json_diagnostics.md), and
-[`JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON`](json_use_legacy_discarded_value_comparison.md)).
+The default value consists of the root namespace (`nlohmann`) and an inline ABI namespace. See
+[`nlohmann` Namespace](../../features/namespace.md#structure) for details.
 
-When the macro is not defined, the library will define it to its default value.
+When the macro is not defined, the library will define it to its default value. Overriding this value has no effect on
+the library.
 
 ## Examples
 
@@ -35,7 +34,8 @@
 ## See also
 
 - [`NLOHMANN_JSON_NAMESPACE_BEGIN, NLOHMANN_JSON_NAMESPACE_END`](nlohmann_json_namespace_begin.md)
+- [`NLOHMANN_JSON_NAMESPACE_NO_VERSION`](nlohmann_json_namespace_no_version.md)
 
 ## Version history
 
-- Added in version 3.11.0.
+- Added in version 3.11.0. Changed inline namespace name in version 3.11.2.
diff --git a/docs/mkdocs/docs/api/macros/nlohmann_json_namespace_begin.md b/docs/mkdocs/docs/api/macros/nlohmann_json_namespace_begin.md
index 5fd8fba..1374264 100644
--- a/docs/mkdocs/docs/api/macros/nlohmann_json_namespace_begin.md
+++ b/docs/mkdocs/docs/api/macros/nlohmann_json_namespace_begin.md
@@ -1,30 +1,35 @@
 # NLOHMANN_JSON_NAMESPACE_BEGIN, NLOHMANN_JSON_NAMESPACE_END
 
 ```cpp
-#define NLOHMANN_JSON_NAMESPACE_BEGIN  // (1)
-#define NLOHMANN_JSON_NAMESPACE_END    // (2)
+#define NLOHMANN_JSON_NAMESPACE_BEGIN /* value */  // (1)
+#define NLOHMANN_JSON_NAMESPACE_END   /* value */  // (2)
 ```
 
-These macros can be used to open and close the `nlohmann` namespace. They include an inline namespace used to
-differentiate symbols when linking multiple versions (including different ABI-affecting macros) of this library.
+These macros can be used to open and close the `nlohmann` namespace. See
+[`nlohmann` Namespace](../../features/namespace.md#structure) for details.
 
 1. Opens the namespace.
-    ```cpp
-    namespace nlohmann
-    {
-    inline namespace json_v3_11_0
-    {
-    ```
-
 2. Closes the namespace.
-    ```cpp
-    }  // namespace nlohmann
-    }  // json_v3_11_0
-    ```
 
 ## Default definition
 
-The default definitions open and close the `nlohmann` as well as an inline  namespace.
+The default definitions open and close the `nlohmann` namespace. The precise definition of
+[`NLOHMANN_JSON_NAMESPACE_BEGIN`] varies as described [here](../../features/namespace.md#structure).
+
+1. Default definition of `NLOHMANN_JSON_NAMESPACE_BEGIN`:
+
+    ```cpp
+    namespace nlohmann
+    {
+    inline namespace json_abi_v3_11_2
+    {
+    ```
+
+2. Default definition of `NLOHMANN_JSON_NAMESPACE_END`:
+    ```cpp
+    }  // namespace json_abi_v3_11_2
+    }  // namespace nlohmann
+    ```
 
 When these macros are not defined, the library will define them to their default definitions.
 
@@ -32,7 +37,7 @@
 
 ??? example
 
-    The example shows an example how to use `NLOHMANN_JSON_NAMESPACE_BEGIN`/`NLOHMANN_JSON_NAMESPACE_END` from the
+    The example shows how to use `NLOHMANN_JSON_NAMESPACE_BEGIN`/`NLOHMANN_JSON_NAMESPACE_END` from the
     [How do I convert third-party types?](../../features/arbitrary_types.md#how-do-i-convert-third-party-types) page.
 
     ```cpp
@@ -47,8 +52,10 @@
 
 ## See also
 
+- [`nlohmann` Namespace](../../features/namespace.md)
 - [NLOHMANN_JSON_NAMESPACE](nlohmann_json_namespace.md)
+- [`NLOHMANN_JSON_NAMESPACE_NO_VERSION`](nlohmann_json_namespace_no_version.md)
 
 ## Version history
 
-- Added in version 3.11.0.
+- Added in version 3.11.0. Changed inline namespace name in version 3.11.2.
diff --git a/docs/mkdocs/docs/api/macros/nlohmann_json_namespace_no_version.md b/docs/mkdocs/docs/api/macros/nlohmann_json_namespace_no_version.md
new file mode 100644
index 0000000..9e2a52d
--- /dev/null
+++ b/docs/mkdocs/docs/api/macros/nlohmann_json_namespace_no_version.md
@@ -0,0 +1,45 @@
+# NLOHMANN_JSON_NAMESPACE_NO_VERSION
+
+```cpp
+#define NLOHMANN_JSON_NAMESPACE_NO_VERSION /* value */
+```
+
+If defined to `1`, the version component is omitted from the inline namespace. See
+[`nlohmann` Namespace](../../features/namespace.md#structure) for details.
+
+## Default definition
+
+The default value is `0`.
+
+```cpp
+#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
+```
+
+When the macro is not defined, the library will define it to its default value.
+
+## Examples
+
+??? example
+
+    The example shows how to use `NLOHMANN_JSON_NAMESPACE_NO_VERSION` to disable the version component of the inline
+    namespace.
+    
+    ```cpp
+    --8<-- "examples/nlohmann_json_namespace_no_version.cpp"
+    ```
+    
+    Output:
+    
+    ```json
+    --8<-- "examples/nlohmann_json_namespace_no_version.output"
+    ```
+
+## See also
+
+- [`nlohmann` Namespace](../../features/namespace.md)
+- [`NLOHMANN_JSON_NAMESPACE`](nlohmann_json_namespace.md)
+- [`NLOHMANN_JSON_NAMESPACE_BEGIN, NLOHMANN_JSON_NAMESPACE_END`](nlohmann_json_namespace_begin.md)
+
+## Version history
+
+- Added in version 3.11.2.
diff --git a/docs/mkdocs/docs/features/namespace.md b/docs/mkdocs/docs/features/namespace.md
new file mode 100644
index 0000000..8cee2cc
--- /dev/null
+++ b/docs/mkdocs/docs/features/namespace.md
@@ -0,0 +1,93 @@
+# `nlohmann` Namespace
+
+The 3.11.0 release introduced an
+[inline namespace](https://en.cppreference.com/w/cpp/language/namespace#Inline_namespaces) to allow different parts of
+a codebase to safely use different versions of the JSON library as long as they never exchange instances of library
+types.
+
+## Structure
+
+The complete default namespace name is derived as follows:
+
+- The root namespace is always `nlohmann`.
+- The inline namespace starts with `json_abi` and is followed by serveral optional ABI tags according to the value of
+  these ABI-affecting macros, in order:
+    - [`JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md) defined non-zero appends `_diag`.
+    - [`JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON`](../api/macros/json_use_legacy_discarded_value_comparison.md)
+      defined non-zero appends `_ldvcmp`.
+- The inline namespace ends with the suffix `_v` followed by the 3 components of the version number separated by
+  underscores. To omit the version component, see [Disabling the version component](#disabling-the-version-component)
+  below.
+
+For example, the namespace name for version 3.11.2 with `JSON_DIAGNOSTICS` defined to `1` is:
+
+```cpp
+nlohmann::json_abi_diag_v3_11_2
+```
+
+## Purpose
+
+Several incompatibilities have been observed. Amongst the most common ones is linking code compiled with different
+definitions of [`JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md). This is illustrated in the diagram below.
+
+```plantuml
+[**nlohmann_json (v3.10.5)**\nJSON_DIAGNOSTICS=0] as [json]
+[**nlohmann_json (v3.10.5)**\nJSON_DIAGNOSTICS=1] as [json_diag]
+[**some_library**] as [library]
+[**application**] as [app]
+
+[library] ..|> [json]
+[app] ..|> [json_diag]
+[app] ..|>[library]
+```
+
+In releases prior to 3.11.0, mixing any version of the JSON library with different `JSON_DIAGNOSTICS` settings would
+result in a crashing application. If `some_library` never passes instances of JSON library types to the application,
+this scenario became safe in version 3.11.0 and above due to the inline namespace yielding distinct symbol names.
+
+## Limitations
+
+Neither the compiler nor the linker will issue as much as a warning when translation units – intended to be linked
+together and that include different versions and/or configurations of the JSON library – exchange and use library
+types.
+
+There is an exception when forward declarations are used (i.e., when including `json_fwd.hpp`) in which case the linker
+may complain about undefined references.
+
+## Disabling the version component
+
+Different versions are not necessarily ABI-incompatible, but the project does not actively track changes in the ABI and
+recommends that all parts of a codebase exchanging library types be built with the same version. Users can, **at their
+own risk**, disable the version component of the linline namespace, allowing different versions – but not
+configurations – to be used in cases where the linker would otherwise output undefined reference errors.
+
+To do so, define [`NLOHMANN_JSON_NAMESPACE_NO_VERSION`](../api/macros/nlohmann_json_namespace_no_version.md) to `1`.
+
+This applies to version 3.11.2 and above only, versions 3.11.0 and 3.11.1 can apply the technique described in the next
+section to emulate the effect of the `NLOHMANN_JSON_NAMESPACE_NO_VERSION` macro.
+
+!!! danger "Use at your own risk"
+
+    Disabling the namespace version component and mixing ABI-incompatible versions will result in crashes or incorrect
+    behavior. You have been warned!
+## Disabling the inline namespace completely
+
+When interoperability with code using a pre-3.11.0 version of the library is required, users can, **at their own risk**
+restore the old namespace layout by redefining
+[`NLOHMANN_JSON_NAMESPACE_BEGIN, NLOHMANN_JSON_NAMESPACE_END`](../api/macros/nlohmann_json_namespace_begin.md) as
+follows:
+
+```cpp
+#define NLOHMANN_JSON_NAMESPACE_BEGIN  namespace nlohmann {
+#define NLOHMANN_JSON_NAMESPACE_END    }
+```
+
+!!! danger "Use at your own risk"
+
+    Overriding the namespace and mixing ABI-incompatible versions will result in crashes or incorrect behavior. You
+    have been warned!
+
+## Version history
+
+- Introduced inline namespace (`json_v3_11_0[_abi-tag]*`) in version 3.11.0.
+- Changed structure of inline namespace in version 3.11.2.
diff --git a/docs/mkdocs/mkdocs.yml b/docs/mkdocs/mkdocs.yml
index f88784f..545584a 100644
--- a/docs/mkdocs/mkdocs.yml
+++ b/docs/mkdocs/mkdocs.yml
@@ -58,6 +58,7 @@
     - features/json_pointer.md
     - features/json_patch.md
     - features/merge_patch.md
+    - 'nlohmann Namespace': features/namespace.md
     - features/object_order.md
     - Parsing:
         - features/parsing/index.md
@@ -270,6 +271,7 @@
         - 'NLOHMANN_JSON_NAMESPACE': api/macros/nlohmann_json_namespace.md
         - 'NLOHMANN_JSON_NAMESPACE_BEGIN': api/macros/nlohmann_json_namespace_begin.md
         - 'NLOHMANN_JSON_NAMESPACE_END': api/macros/nlohmann_json_namespace_begin.md
+        - 'NLOHMANN_JSON_NAMESPACE_NO_VERSION': api/macros/nlohmann_json_namespace_no_version.md
         - 'NLOHMANN_JSON_SERIALIZE_ENUM': api/macros/nlohmann_json_serialize_enum.md
         - 'NLOHMANN_JSON_VERSION_MAJOR': api/macros/nlohmann_json_version_major.md
         - 'NLOHMANN_JSON_VERSION_MINOR': api/macros/nlohmann_json_version_major.md
diff --git a/include/nlohmann/detail/abi_macros.hpp b/include/nlohmann/detail/abi_macros.hpp
index dac3c58..867b369 100644
--- a/include/nlohmann/detail/abi_macros.hpp
+++ b/include/nlohmann/detail/abi_macros.hpp
@@ -42,38 +42,59 @@
     #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
 #endif
 
-#define NLOHMANN_JSON_ABI_PREFIX_EX(major, minor, patch) \
-    json_v ## major ## _ ## minor ## _ ## patch
-#define NLOHMANN_JSON_ABI_PREFIX(major, minor, patch) \
-    NLOHMANN_JSON_ABI_PREFIX_EX(major, minor, patch)
+#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
+    #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
+#endif
 
-#define NLOHMANN_JSON_ABI_CONCAT_EX(a, b, c) a ## b ## c
-#define NLOHMANN_JSON_ABI_CONCAT(a, b, c) \
-    NLOHMANN_JSON_ABI_CONCAT_EX(a, b, c)
+// Construct the namespace ABI tags component
+#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
+#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
+    NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
 
-#define NLOHMANN_JSON_ABI_STRING                                    \
-    NLOHMANN_JSON_ABI_CONCAT(                                       \
-            NLOHMANN_JSON_ABI_PREFIX(                               \
-                    NLOHMANN_JSON_VERSION_MAJOR,                    \
-                    NLOHMANN_JSON_VERSION_MINOR,                    \
-                    NLOHMANN_JSON_VERSION_PATCH),                   \
-            NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS,                      \
+#define NLOHMANN_JSON_ABI_TAGS                                       \
+    NLOHMANN_JSON_ABI_TAGS_CONCAT(                                   \
+            NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS,                       \
             NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
 
+// Construct the namespace version component
+#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
+    _v ## major ## _ ## minor ## _ ## patch
+#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
+    NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
+
+#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
+#define NLOHMANN_JSON_NAMESPACE_VERSION
+#else
+#define NLOHMANN_JSON_NAMESPACE_VERSION                                 \
+    NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
+                                           NLOHMANN_JSON_VERSION_MINOR, \
+                                           NLOHMANN_JSON_VERSION_PATCH)
+#endif
+
+// Combine namespace components
+#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
+#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
+    NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
+
 #ifndef NLOHMANN_JSON_NAMESPACE
-    #define NLOHMANN_JSON_NAMESPACE nlohmann::NLOHMANN_JSON_ABI_STRING
+#define NLOHMANN_JSON_NAMESPACE               \
+    nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
+            NLOHMANN_JSON_ABI_TAGS,           \
+            NLOHMANN_JSON_NAMESPACE_VERSION)
 #endif
 
 #ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
-#define NLOHMANN_JSON_NAMESPACE_BEGIN         \
-    namespace nlohmann                        \
-    {                                         \
-    inline namespace NLOHMANN_JSON_ABI_STRING \
+#define NLOHMANN_JSON_NAMESPACE_BEGIN                \
+    namespace nlohmann                               \
+    {                                                \
+    inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
+                NLOHMANN_JSON_ABI_TAGS,              \
+                NLOHMANN_JSON_NAMESPACE_VERSION)     \
     {
 #endif
 
 #ifndef NLOHMANN_JSON_NAMESPACE_END
-#define NLOHMANN_JSON_NAMESPACE_END \
-    }  /* namespace (abi_string) */ \
-    }  /* namespace nlohmann */
+#define NLOHMANN_JSON_NAMESPACE_END                                     \
+    }  /* namespace (inline namespace) NOLINT(readability/namespace) */ \
+    }  // namespace nlohmann
 #endif
diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp
index 2689c41..6f956da 100644
--- a/single_include/nlohmann/json.hpp
+++ b/single_include/nlohmann/json.hpp
@@ -90,40 +90,61 @@
     #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
 #endif
 
-#define NLOHMANN_JSON_ABI_PREFIX_EX(major, minor, patch) \
-    json_v ## major ## _ ## minor ## _ ## patch
-#define NLOHMANN_JSON_ABI_PREFIX(major, minor, patch) \
-    NLOHMANN_JSON_ABI_PREFIX_EX(major, minor, patch)
+#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
+    #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
+#endif
 
-#define NLOHMANN_JSON_ABI_CONCAT_EX(a, b, c) a ## b ## c
-#define NLOHMANN_JSON_ABI_CONCAT(a, b, c) \
-    NLOHMANN_JSON_ABI_CONCAT_EX(a, b, c)
+// Construct the namespace ABI tags component
+#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
+#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
+    NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
 
-#define NLOHMANN_JSON_ABI_STRING                                    \
-    NLOHMANN_JSON_ABI_CONCAT(                                       \
-            NLOHMANN_JSON_ABI_PREFIX(                               \
-                    NLOHMANN_JSON_VERSION_MAJOR,                    \
-                    NLOHMANN_JSON_VERSION_MINOR,                    \
-                    NLOHMANN_JSON_VERSION_PATCH),                   \
-            NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS,                      \
+#define NLOHMANN_JSON_ABI_TAGS                                       \
+    NLOHMANN_JSON_ABI_TAGS_CONCAT(                                   \
+            NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS,                       \
             NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
 
+// Construct the namespace version component
+#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
+    _v ## major ## _ ## minor ## _ ## patch
+#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
+    NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
+
+#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
+#define NLOHMANN_JSON_NAMESPACE_VERSION
+#else
+#define NLOHMANN_JSON_NAMESPACE_VERSION                                 \
+    NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
+                                           NLOHMANN_JSON_VERSION_MINOR, \
+                                           NLOHMANN_JSON_VERSION_PATCH)
+#endif
+
+// Combine namespace components
+#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
+#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
+    NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
+
 #ifndef NLOHMANN_JSON_NAMESPACE
-    #define NLOHMANN_JSON_NAMESPACE nlohmann::NLOHMANN_JSON_ABI_STRING
+#define NLOHMANN_JSON_NAMESPACE               \
+    nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
+            NLOHMANN_JSON_ABI_TAGS,           \
+            NLOHMANN_JSON_NAMESPACE_VERSION)
 #endif
 
 #ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
-#define NLOHMANN_JSON_NAMESPACE_BEGIN         \
-    namespace nlohmann                        \
-    {                                         \
-    inline namespace NLOHMANN_JSON_ABI_STRING \
+#define NLOHMANN_JSON_NAMESPACE_BEGIN                \
+    namespace nlohmann                               \
+    {                                                \
+    inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
+                NLOHMANN_JSON_ABI_TAGS,              \
+                NLOHMANN_JSON_NAMESPACE_VERSION)     \
     {
 #endif
 
 #ifndef NLOHMANN_JSON_NAMESPACE_END
-#define NLOHMANN_JSON_NAMESPACE_END \
-    }  /* namespace (abi_string) */ \
-    }  /* namespace nlohmann */
+#define NLOHMANN_JSON_NAMESPACE_END                                     \
+    }  /* namespace (inline namespace) NOLINT(readability/namespace) */ \
+    }  // namespace nlohmann
 #endif
 
 // #include <nlohmann/detail/conversions/from_json.hpp>
diff --git a/single_include/nlohmann/json_fwd.hpp b/single_include/nlohmann/json_fwd.hpp
index 0718f3f..6d0283a 100644
--- a/single_include/nlohmann/json_fwd.hpp
+++ b/single_include/nlohmann/json_fwd.hpp
@@ -60,40 +60,61 @@
     #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
 #endif
 
-#define NLOHMANN_JSON_ABI_PREFIX_EX(major, minor, patch) \
-    json_v ## major ## _ ## minor ## _ ## patch
-#define NLOHMANN_JSON_ABI_PREFIX(major, minor, patch) \
-    NLOHMANN_JSON_ABI_PREFIX_EX(major, minor, patch)
+#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
+    #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
+#endif
 
-#define NLOHMANN_JSON_ABI_CONCAT_EX(a, b, c) a ## b ## c
-#define NLOHMANN_JSON_ABI_CONCAT(a, b, c) \
-    NLOHMANN_JSON_ABI_CONCAT_EX(a, b, c)
+// Construct the namespace ABI tags component
+#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
+#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
+    NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
 
-#define NLOHMANN_JSON_ABI_STRING                                    \
-    NLOHMANN_JSON_ABI_CONCAT(                                       \
-            NLOHMANN_JSON_ABI_PREFIX(                               \
-                    NLOHMANN_JSON_VERSION_MAJOR,                    \
-                    NLOHMANN_JSON_VERSION_MINOR,                    \
-                    NLOHMANN_JSON_VERSION_PATCH),                   \
-            NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS,                      \
+#define NLOHMANN_JSON_ABI_TAGS                                       \
+    NLOHMANN_JSON_ABI_TAGS_CONCAT(                                   \
+            NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS,                       \
             NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
 
+// Construct the namespace version component
+#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
+    _v ## major ## _ ## minor ## _ ## patch
+#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
+    NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
+
+#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
+#define NLOHMANN_JSON_NAMESPACE_VERSION
+#else
+#define NLOHMANN_JSON_NAMESPACE_VERSION                                 \
+    NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
+                                           NLOHMANN_JSON_VERSION_MINOR, \
+                                           NLOHMANN_JSON_VERSION_PATCH)
+#endif
+
+// Combine namespace components
+#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
+#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
+    NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
+
 #ifndef NLOHMANN_JSON_NAMESPACE
-    #define NLOHMANN_JSON_NAMESPACE nlohmann::NLOHMANN_JSON_ABI_STRING
+#define NLOHMANN_JSON_NAMESPACE               \
+    nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
+            NLOHMANN_JSON_ABI_TAGS,           \
+            NLOHMANN_JSON_NAMESPACE_VERSION)
 #endif
 
 #ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
-#define NLOHMANN_JSON_NAMESPACE_BEGIN         \
-    namespace nlohmann                        \
-    {                                         \
-    inline namespace NLOHMANN_JSON_ABI_STRING \
+#define NLOHMANN_JSON_NAMESPACE_BEGIN                \
+    namespace nlohmann                               \
+    {                                                \
+    inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
+                NLOHMANN_JSON_ABI_TAGS,              \
+                NLOHMANN_JSON_NAMESPACE_VERSION)     \
     {
 #endif
 
 #ifndef NLOHMANN_JSON_NAMESPACE_END
-#define NLOHMANN_JSON_NAMESPACE_END \
-    }  /* namespace (abi_string) */ \
-    }  /* namespace nlohmann */
+#define NLOHMANN_JSON_NAMESPACE_END                                     \
+    }  /* namespace (inline namespace) NOLINT(readability/namespace) */ \
+    }  // namespace nlohmann
 #endif
 
 
diff --git a/tests/abi/CMakeLists.txt b/tests/abi/CMakeLists.txt
index c1ae543..ba90837 100644
--- a/tests/abi/CMakeLists.txt
+++ b/tests/abi/CMakeLists.txt
@@ -25,5 +25,6 @@
 target_link_libraries(abi_compat_main PUBLIC abi_compat_common)
 
 # add individual tests
+add_subdirectory(config)
 add_subdirectory(diag)
 add_subdirectory(inline_ns)
diff --git a/tests/abi/config/CMakeLists.txt b/tests/abi/config/CMakeLists.txt
new file mode 100644
index 0000000..3a83676
--- /dev/null
+++ b/tests/abi/config/CMakeLists.txt
@@ -0,0 +1,22 @@
+# test the different options to change the namespace
+
+# test default namespace
+add_executable(abi_config_default default.cpp)
+target_link_libraries(abi_config_default PRIVATE abi_compat_main)
+add_test(
+    NAME test-abi_config_default
+    COMMAND abi_config_default ${DOCTEST_TEST_FILTER})
+
+# test no version namespace
+add_executable(abi_config_noversion noversion.cpp)
+target_link_libraries(abi_config_noversion PRIVATE abi_compat_main)
+add_test(
+    NAME test-abi_config_noversion
+    COMMAND abi_config_noversion ${DOCTEST_TEST_FILTER})
+
+# test custom namespace
+add_executable(abi_config_custom custom.cpp)
+target_link_libraries(abi_config_custom PRIVATE abi_compat_main)
+add_test(
+    NAME test-abi_config_custom
+    COMMAND abi_config_custom ${DOCTEST_TEST_FILTER})
diff --git a/tests/abi/config/config.hpp b/tests/abi/config/config.hpp
new file mode 100644
index 0000000..a824625
--- /dev/null
+++ b/tests/abi/config/config.hpp
@@ -0,0 +1,35 @@
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
+// |  |  |__   |  |  | | | |  version 3.11.1
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+#pragma once
+
+#include "doctest.h"
+
+#include <iostream>
+#include <regex>
+#include <string>
+
+#define STRINGIZE_EX(x) #x
+#define STRINGIZE(x) STRINGIZE_EX(x)
+
+template<typename T>
+std::string namespace_name(std::string ns, T* /*unused*/ = nullptr) // NOLINT(performance-unnecessary-value-param)
+{
+#if DOCTEST_MSVC && !DOCTEST_CLANG
+    ns = __FUNCSIG__;
+#elif !DOCTEST_CLANG
+    ns = __PRETTY_FUNCTION__;
+#endif
+    std::smatch m;
+
+    // extract the true namespace name from the function signature
+    CAPTURE(ns);
+    CHECK(std::regex_search(ns, m, std::regex("nlohmann(::[a-zA-Z0-9_]+)*::basic_json")));
+
+    return m.str();
+}
diff --git a/tests/abi/config/custom.cpp b/tests/abi/config/custom.cpp
new file mode 100644
index 0000000..9567e6c
--- /dev/null
+++ b/tests/abi/config/custom.cpp
@@ -0,0 +1,33 @@
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
+// |  |  |__   |  |  | | | |  version 3.11.1
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+#include "doctest_compatibility.h"
+
+#include "config.hpp"
+
+// define custom namespace
+#define NLOHMANN_JSON_NAMESPACE nlohmann // this line may be omitted
+#define NLOHMANN_JSON_NAMESPACE_BEGIN namespace nlohmann {
+#define NLOHMANN_JSON_NAMESPACE_END }
+#include <nlohmann/json_fwd.hpp>
+
+TEST_CASE("custom namespace")
+{
+    // GCC 4.8 fails with regex_error
+#if !DOCTEST_GCC || DOCTEST_GCC >= DOCTEST_COMPILER(4, 9, 0)
+    SECTION("namespace matches expectation")
+    {
+        std::string expected = "nlohmann::basic_json";
+
+        // fallback for Clang
+        std::string ns{STRINGIZE(NLOHMANN_JSON_NAMESPACE) "::basic_json"};
+
+        CHECK(namespace_name<nlohmann::json>(ns) == expected);
+    }
+#endif
+}
diff --git a/tests/abi/config/default.cpp b/tests/abi/config/default.cpp
new file mode 100644
index 0000000..0562db7
--- /dev/null
+++ b/tests/abi/config/default.cpp
@@ -0,0 +1,41 @@
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
+// |  |  |__   |  |  | | | |  version 3.11.1
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+#include "doctest_compatibility.h"
+
+#include "config.hpp"
+
+#include <nlohmann/json_fwd.hpp>
+
+TEST_CASE("default namespace")
+{
+    // GCC 4.8 fails with regex_error
+#if !DOCTEST_GCC || DOCTEST_GCC >= DOCTEST_COMPILER(4, 9, 0)
+    SECTION("namespace matches expectation")
+    {
+        std::string expected = "nlohmann::json_abi";
+
+#if JSON_DIAGNOSTICS
+        expected += "_diag";
+#endif
+
+#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
+        expected += "_ldvcmp";
+#endif
+
+        expected += "_v" STRINGIZE(NLOHMANN_JSON_VERSION_MAJOR);
+        expected += "_" STRINGIZE(NLOHMANN_JSON_VERSION_MINOR);
+        expected += "_" STRINGIZE(NLOHMANN_JSON_VERSION_PATCH) "::basic_json";
+
+        // fallback for Clang
+        std::string ns{STRINGIZE(NLOHMANN_JSON_NAMESPACE) "::basic_json"};
+
+        CHECK(namespace_name<nlohmann::json>(ns) == expected);
+    }
+#endif
+}
diff --git a/tests/abi/config/noversion.cpp b/tests/abi/config/noversion.cpp
new file mode 100644
index 0000000..f8a5530
--- /dev/null
+++ b/tests/abi/config/noversion.cpp
@@ -0,0 +1,40 @@
+//     __ _____ _____ _____
+//  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
+// |  |  |__   |  |  | | | |  version 3.11.1
+// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+#include "doctest_compatibility.h"
+
+#include "config.hpp"
+
+#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 1
+#include <nlohmann/json_fwd.hpp>
+
+TEST_CASE("default namespace without version component")
+{
+    // GCC 4.8 fails with regex_error
+#if !DOCTEST_GCC || DOCTEST_GCC >= DOCTEST_COMPILER(4, 9, 0)
+    SECTION("namespace matches expectation")
+    {
+        std::string expected = "nlohmann::json_abi";
+
+#if JSON_DIAGNOSTICS
+        expected += "_diag";
+#endif
+
+#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
+        expected += "_ldvcmp";
+#endif
+
+        expected += "::basic_json";
+
+        // fallback for Clang
+        std::string ns{STRINGIZE(NLOHMANN_JSON_NAMESPACE) "::basic_json"};
+
+        CHECK(namespace_name<nlohmann::json>(ns) == expected);
+    }
+#endif
+}
diff --git a/tests/abi/include/nlohmann/json_v3_10_5.hpp b/tests/abi/include/nlohmann/json_v3_10_5.hpp
index cb27e05..8799555 100644
--- a/tests/abi/include/nlohmann/json_v3_10_5.hpp
+++ b/tests/abi/include/nlohmann/json_v3_10_5.hpp
@@ -36,8 +36,8 @@
  * file doc/README.md.                                                      *
 \****************************************************************************/
 
-#ifndef INCLUDE_NLOHMANN_JSON_HPP_
-#define INCLUDE_NLOHMANN_JSON_HPP_
+#ifndef INCLUDE_NLOHMANN_JSON_V3_10_5_HPP_
+#define INCLUDE_NLOHMANN_JSON_V3_10_5_HPP_
 
 #define NLOHMANN_JSON_VERSION_MAJOR 3
 #define NLOHMANN_JSON_VERSION_MINOR 10
@@ -22088,4 +22088,4 @@
 
 
 
-#endif  // INCLUDE_NLOHMANN_JSON_HPP_
+#endif  // INCLUDE_NLOHMANN_JSON_V3_10_5_HPP_
diff --git a/tools/gdb_pretty_printer/nlohmann-json.py b/tools/gdb_pretty_printer/nlohmann-json.py
index 774756d..0099f9c 100644
--- a/tools/gdb_pretty_printer/nlohmann-json.py
+++ b/tools/gdb_pretty_printer/nlohmann-json.py
@@ -1,7 +1,7 @@
 import gdb
 import re
 
-ns_pattern = re.compile(r'nlohmann::json_v(?P<v_major>\d+)_(?P<v_minor>\d+)_(?P<v_patch>\d+)(?P<tags>\w*)::(?P<name>.+)')
+ns_pattern = re.compile(r'nlohmann(::json_abi(?P<tags>\w*)(_v(?P<v_major>\d+)_(?P<v_minor>\d+)_(?P<v_patch>\d+))?)?::(?P<name>.+)')
 class JsonValuePrinter:
     "Print a json-value"
 
@@ -26,7 +26,7 @@
                     return gdb.default_visualizer(union_val.dereference())
                 else:
                     return JsonValuePrinter(union_val)
-            except:
+            except Exception:
                 return JsonValuePrinter(val['m_type'])
 
 gdb.pretty_printers.append(json_lookup_function)