new file mode 100644
@@ -0,0 +1,368 @@
+From c67034e4b4c722579ee15fddb8e4af8f04252b08 Mon Sep 17 00:00:00 2001
+From: Jordan Bayles <bayles.jordan@gmail.com>
+Date: Thu, 9 Apr 2026 10:37:08 -0700
+Subject: [PATCH] Fix C++11 ABI breakage when compiled with C++17 #1668 (#1675)
+
+When JSONCPP_HAS_STRING_VIEW was defined, the library dropped the
+`const char*` and `const String&` overloads for `operator[]`, `get`,
+`removeMember`, and `isMember`, breaking ABI compatibility for projects
+consuming the library with C++11.
+
+This change unconditionally declares and defines the legacy overloads
+so they are always exported, restoring compatibility.
+
+This commit completely eliminates the ABI breakage that occurs across
+C++ standard boundaries when using `std::string_view`.
+
+Previously, when the library was built with C++17+, CMake would leak
+`JSONCPP_HAS_STRING_VIEW=1` as a PUBLIC definition. A C++11 consumer
+would receive this definition, attempt to parse the header, and fail
+with compiler errors because `std::string_view` is not available in
+their environment.
+
+Conversely, if the library was built in C++11 (without `string_view`
+symbols), a C++17 consumer would naturally define
+`JSONCPP_HAS_STRING_VIEW` based on `__cplusplus` inside `value.h`. The
+consumer would then call the declared `string_view` methods, resulting
+in linker errors because the methods weren't compiled into the library.
+
+By moving all `std::string_view` overloads directly into `value.h` as
+`inline` methods that delegate to the fundamental
+`const char*, const char*` methods:
+1. The consumer's compiler dictates whether the overloads are visible
+ (via `__cplusplus >= 201703L`).
+2. The consumer compiles the inline wrappers locally, removing any
+ reliance on the library's exported symbols for `std::string_view`.
+3. CMake no longer needs to pollute the consumer's environment with
+ PUBLIC compile definitions.
+
+Backported only the library/header changes. Upstream CI and example
+test additions are omitted.
+
+Upstream-Status: Backport [https://github.com/open-source-parsers/jsoncpp/commit/c67034e4b4c722579ee15fddb8e4af8f04252b08]
+Signed-off-by: Ernest Van Hoecke <ernest.vanhoecke@toradex.com>
+---
+ include/json/value.h | 54 ++++++++++++++++++++----------
+ src/lib_json/CMakeLists.txt | 9 -----
+ src/lib_json/json_value.cpp | 66 -------------------------------------
+ 3 files changed, 36 insertions(+), 93 deletions(-)
+
+diff --git a/include/json/value.h b/include/json/value.h
+index f32f45609365..2007e6b4251d 100644
+--- a/include/json/value.h
++++ b/include/json/value.h
+@@ -357,7 +357,8 @@ public:
+ Value(const StaticString& value);
+ Value(const String& value);
+ #ifdef JSONCPP_HAS_STRING_VIEW
+- Value(std::string_view value);
++ inline Value(std::string_view value)
++ : Value(value.data(), value.data() + value.length()) {}
+ #endif
+ Value(bool value);
+ Value(std::nullptr_t ptr) = delete;
+@@ -405,7 +406,14 @@ public:
+ /** Get string_view of string-value.
+ * \return false if !string. (Seg-fault if str is NULL.)
+ */
+- bool getString(std::string_view* str) const;
++ inline bool getString(std::string_view* str) const {
++ char const* begin;
++ char const* end;
++ if (!getString(&begin, &end))
++ return false;
++ *str = std::string_view(begin, static_cast<size_t>(end - begin));
++ return true;
++ }
+ #endif
+ Int asInt() const;
+ UInt asUInt() const;
+@@ -496,12 +504,19 @@ public:
+ #ifdef JSONCPP_HAS_STRING_VIEW
+ /// Access an object value by name, create a null member if it does not exist.
+ /// \param key may contain embedded nulls.
+- Value& operator[](std::string_view key);
++ inline Value& operator[](std::string_view key) {
++ return resolveReference(key.data(), key.data() + key.length());
++ }
+ /// Access an object value by name, returns null if there is no member with
+ /// that name.
+ /// \param key may contain embedded nulls.
+- const Value& operator[](std::string_view key) const;
+-#else
++ inline const Value& operator[](std::string_view key) const {
++ Value const* found = find(key.data(), key.data() + key.length());
++ if (!found)
++ return nullSingleton();
++ return *found;
++ }
++#endif
+ /// Access an object value by name, create a null member if it does not exist.
+ /// \note Because of our implementation, keys are limited to 2^30 -1 chars.
+ /// Exceeding that will cause an exception.
+@@ -516,7 +531,6 @@ public:
+ /// that name.
+ /// \param key may contain embedded nulls.
+ const Value& operator[](const String& key) const;
+-#endif
+ /** \brief Access an object value by name, create a null member if it does not
+ * exist.
+ *
+@@ -533,8 +547,10 @@ public:
+ #ifdef JSONCPP_HAS_STRING_VIEW
+ /// Return the member named key if it exist, defaultValue otherwise.
+ /// \note deep copy
+- Value get(std::string_view key, const Value& defaultValue) const;
+-#else
++ inline Value get(std::string_view key, const Value& defaultValue) const {
++ return get(key.data(), key.data() + key.length(), defaultValue);
++ }
++#endif
+ /// Return the member named key if it exist, defaultValue otherwise.
+ /// \note deep copy
+ Value get(const char* key, const Value& defaultValue) const;
+@@ -542,7 +558,6 @@ public:
+ /// \note deep copy
+ /// \param key may contain embedded nulls.
+ Value get(const String& key, const Value& defaultValue) const;
+-#endif
+ /// Return the member named key if it exist, defaultValue otherwise.
+ /// \note deep copy
+ /// \note key may contain embedded nulls.
+@@ -588,13 +603,14 @@ public:
+ /// \pre type() is objectValue or nullValue
+ /// \post type() is unchanged
+ #if JSONCPP_HAS_STRING_VIEW
+- void removeMember(std::string_view key);
+-#else
++ inline void removeMember(std::string_view key) {
++ removeMember(key.data(), key.data() + key.length(), nullptr);
++ }
++#endif
+ void removeMember(const char* key);
+ /// Same as removeMember(const char*)
+ /// \param key may contain embedded nulls.
+ void removeMember(const String& key);
+-#endif
+ /** \brief Remove the named map member.
+ *
+ * Update 'removed' iff removed.
+@@ -602,13 +618,14 @@ public:
+ * \return true iff removed (no exceptions)
+ */
+ #if JSONCPP_HAS_STRING_VIEW
+- bool removeMember(std::string_view key, Value* removed);
+-#else
++ inline bool removeMember(std::string_view key, Value* removed) {
++ return removeMember(key.data(), key.data() + key.length(), removed);
++ }
++#endif
+ bool removeMember(String const& key, Value* removed);
+ /// Same as removeMember(const char* begin, const char* end, Value* removed),
+ /// but 'key' is null-terminated.
+ bool removeMember(const char* key, Value* removed);
+-#endif
+ /// Same as removeMember(String const& key, Value* removed)
+ bool removeMember(const char* begin, const char* end, Value* removed);
+ /** \brief Remove the indexed array element.
+@@ -622,15 +639,16 @@ public:
+ #ifdef JSONCPP_HAS_STRING_VIEW
+ /// Return true if the object has a member named key.
+ /// \param key may contain embedded nulls.
+- bool isMember(std::string_view key) const;
+-#else
++ inline bool isMember(std::string_view key) const {
++ return isMember(key.data(), key.data() + key.length());
++ }
++#endif
+ /// Return true if the object has a member named key.
+ /// \note 'key' must be null-terminated.
+ bool isMember(const char* key) const;
+ /// Return true if the object has a member named key.
+ /// \param key may contain embedded nulls.
+ bool isMember(const String& key) const;
+-#endif
+ /// Same as isMember(String const& key)const
+ bool isMember(const char* begin, const char* end) const;
+
+diff --git a/src/lib_json/CMakeLists.txt b/src/lib_json/CMakeLists.txt
+index 03e9335525ca..a0695e9eba83 100644
+--- a/src/lib_json/CMakeLists.txt
++++ b/src/lib_json/CMakeLists.txt
+@@ -131,9 +131,6 @@ if(BUILD_SHARED_LIBS)
+
+ target_compile_features(${SHARED_LIB} PUBLIC ${REQUIRED_FEATURES})
+
+- if(JSONCPP_HAS_STRING_VIEW)
+- target_compile_definitions(${SHARED_LIB} PUBLIC JSONCPP_HAS_STRING_VIEW=1)
+- endif()
+
+ target_include_directories(${SHARED_LIB} PUBLIC
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+@@ -168,9 +165,6 @@ if(BUILD_STATIC_LIBS)
+
+ target_compile_features(${STATIC_LIB} PUBLIC ${REQUIRED_FEATURES})
+
+- if(JSONCPP_HAS_STRING_VIEW)
+- target_compile_definitions(${STATIC_LIB} PUBLIC JSONCPP_HAS_STRING_VIEW=1)
+- endif()
+
+ target_include_directories(${STATIC_LIB} PUBLIC
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+@@ -198,9 +192,6 @@ if(BUILD_OBJECT_LIBS)
+
+ target_compile_features(${OBJECT_LIB} PUBLIC ${REQUIRED_FEATURES})
+
+- if(JSONCPP_HAS_STRING_VIEW)
+- target_compile_definitions(${OBJECT_LIB} PUBLIC JSONCPP_HAS_STRING_VIEW=1)
+- endif()
+
+ target_include_directories(${OBJECT_LIB} PUBLIC
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp
+index 74f77896fa7b..a8eb72d6b75f 100644
+--- a/src/lib_json/json_value.cpp
++++ b/src/lib_json/json_value.cpp
+@@ -441,14 +441,6 @@ Value::Value(const String& value) {
+ value.data(), static_cast<unsigned>(value.length()));
+ }
+
+-#ifdef JSONCPP_HAS_STRING_VIEW
+-Value::Value(std::string_view value) {
+- initBasic(stringValue, true);
+- value_.string_ = duplicateAndPrefixStringValue(
+- value.data(), static_cast<unsigned>(value.length()));
+-}
+-#endif
+-
+ Value::Value(const StaticString& value) {
+ initBasic(stringValue);
+ value_.string_ = const_cast<char*>(value.c_str());
+@@ -656,21 +648,6 @@ bool Value::getString(char const** begin, char const** end) const {
+ return true;
+ }
+
+-#ifdef JSONCPP_HAS_STRING_VIEW
+-bool Value::getString(std::string_view* str) const {
+- if (type() != stringValue)
+- return false;
+- if (value_.string_ == nullptr)
+- return false;
+- const char* begin;
+- unsigned length;
+- decodePrefixedString(this->isAllocated(), this->value_.string_, &length,
+- &begin);
+- *str = std::string_view(begin, length);
+- return true;
+-}
+-#endif
+-
+ String Value::asString() const {
+ switch (type()) {
+ case nullValue:
+@@ -1190,17 +1167,6 @@ Value* Value::demand(char const* begin, char const* end) {
+ "objectValue or nullValue");
+ return &resolveReference(begin, end);
+ }
+-#ifdef JSONCPP_HAS_STRING_VIEW
+-const Value& Value::operator[](std::string_view key) const {
+- Value const* found = find(key.data(), key.data() + key.length());
+- if (!found)
+- return nullSingleton();
+- return *found;
+-}
+-Value& Value::operator[](std::string_view key) {
+- return resolveReference(key.data(), key.data() + key.length());
+-}
+-#else
+ const Value& Value::operator[](const char* key) const {
+ Value const* found = find(key, key + strlen(key));
+ if (!found)
+@@ -1221,7 +1187,6 @@ Value& Value::operator[](const char* key) {
+ Value& Value::operator[](const String& key) {
+ return resolveReference(key.data(), key.data() + key.length());
+ }
+-#endif
+
+ Value& Value::operator[](const StaticString& key) {
+ return resolveReference(key.c_str());
+@@ -1261,18 +1226,12 @@ Value Value::get(char const* begin, char const* end,
+ Value const* found = find(begin, end);
+ return !found ? defaultValue : *found;
+ }
+-#ifdef JSONCPP_HAS_STRING_VIEW
+-Value Value::get(std::string_view key, const Value& defaultValue) const {
+- return get(key.data(), key.data() + key.length(), defaultValue);
+-}
+-#else
+ Value Value::get(char const* key, Value const& defaultValue) const {
+ return get(key, key + strlen(key), defaultValue);
+ }
+ Value Value::get(String const& key, Value const& defaultValue) const {
+ return get(key.data(), key.data() + key.length(), defaultValue);
+ }
+-#endif
+
+ bool Value::removeMember(const char* begin, const char* end, Value* removed) {
+ if (type() != objectValue) {
+@@ -1288,31 +1247,13 @@ bool Value::removeMember(const char* begin, const char* end, Value* removed) {
+ value_.map_->erase(it);
+ return true;
+ }
+-#ifdef JSONCPP_HAS_STRING_VIEW
+-bool Value::removeMember(std::string_view key, Value* removed) {
+- return removeMember(key.data(), key.data() + key.length(), removed);
+-}
+-#else
+ bool Value::removeMember(const char* key, Value* removed) {
+ return removeMember(key, key + strlen(key), removed);
+ }
+ bool Value::removeMember(String const& key, Value* removed) {
+ return removeMember(key.data(), key.data() + key.length(), removed);
+ }
+-#endif
+-
+-#ifdef JSONCPP_HAS_STRING_VIEW
+-void Value::removeMember(std::string_view key) {
+- JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
+- "in Json::Value::removeMember(): requires objectValue");
+- if (type() == nullValue)
+- return;
+
+- CZString actualKey(key.data(), unsigned(key.length()),
+- CZString::noDuplication);
+- value_.map_->erase(actualKey);
+-}
+-#else
+ void Value::removeMember(const char* key) {
+ JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
+ "in Json::Value::removeMember(): requires objectValue");
+@@ -1323,7 +1264,6 @@ void Value::removeMember(const char* key) {
+ value_.map_->erase(actualKey);
+ }
+ void Value::removeMember(const String& key) { removeMember(key.c_str()); }
+-#endif
+
+ bool Value::removeIndex(ArrayIndex index, Value* removed) {
+ if (type() != arrayValue) {
+@@ -1353,18 +1293,12 @@ bool Value::isMember(char const* begin, char const* end) const {
+ Value const* value = find(begin, end);
+ return nullptr != value;
+ }
+-#ifdef JSONCPP_HAS_STRING_VIEW
+-bool Value::isMember(std::string_view key) const {
+- return isMember(key.data(), key.data() + key.length());
+-}
+-#else
+ bool Value::isMember(char const* key) const {
+ return isMember(key, key + strlen(key));
+ }
+ bool Value::isMember(String const& key) const {
+ return isMember(key.data(), key.data() + key.length());
+ }
+-#endif
+
+ Value::Members Value::getMemberNames() const {
+ JSON_ASSERT_MESSAGE(
+--
+2.43.0
@@ -15,6 +15,7 @@ PE = "1"
SRCREV = "3455302847cf1e4671f1d8f5fa953fd46a7b1404"
SRC_URI = "git://github.com/open-source-parsers/jsoncpp;branch=master;protocol=https;tag=${PV} \
+ file://0001-Fix-C-11-ABI-breakage-when-compiled-with-C-17-1668-1.patch \
file://run-ptest \
"