From 12c5c8867a2467180394d0d942b9f12911cba0f5 Mon Sep 17 00:00:00 2001 From: Jordan Bayles Date: Thu, 14 May 2026 16:08:05 -0700 Subject: [PATCH 1/2] feat: improve type assertion messages with actual ValueType (#1627) When indexing into a Json::Value, several assertions check that the value is an object or array. This commit enhances the error messages by reporting the actual type found, making it easier for users to debug type mismatch issues. Fixes #1627 --- src/lib_json/json_value.cpp | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp index 168251ee1..91cead17f 100644 --- a/src/lib_json/json_value.cpp +++ b/src/lib_json/json_value.cpp @@ -193,6 +193,24 @@ static inline void releaseStringValue(char* value, unsigned) { free(value); } // ValueInternals... // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// + +namespace Json { + +static const char* valueTypeToString(ValueType type) { + switch (type) { + case nullValue: return "nullValue"; + case intValue: return "intValue"; + case uintValue: return "uintValue"; + case realValue: return "realValue"; + case stringValue: return "stringValue"; + case booleanValue: return "booleanValue"; + case arrayValue: return "arrayValue"; + case objectValue: return "objectValue"; + } + return "unknown"; +} + +} // namespace Json // ////////////////////////////////////////////////////////////////// #if !defined(JSON_IS_AMALGAMATION) @@ -929,7 +947,7 @@ void Value::clear() { void Value::resize(ArrayIndex newSize) { JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, - "in Json::Value::resize(): requires arrayValue"); + "in Json::Value::resize(): requires arrayValue, but found " << valueTypeToString(type())); if (type() == nullValue) *this = Value(arrayValue); ArrayIndex oldSize = size(); @@ -1062,7 +1080,7 @@ void Value::dupMeta(const Value& other) { Value& Value::resolveReference(const char* key) { JSON_ASSERT_MESSAGE( type() == nullValue || type() == objectValue, - "in Json::Value::resolveReference(): requires objectValue"); + "in Json::Value::resolveReference(): requires objectValue, but found " << valueTypeToString(type())); if (type() == nullValue) *this = Value(objectValue); CZString actualKey(key, static_cast(strlen(key)), @@ -1081,7 +1099,7 @@ Value& Value::resolveReference(const char* key) { Value& Value::resolveReference(char const* key, char const* end) { JSON_ASSERT_MESSAGE( type() == nullValue || type() == objectValue, - "in Json::Value::resolveReference(key, end): requires objectValue"); + "in Json::Value::resolveReference(key, end): requires objectValue, but found " << valueTypeToString(type())); if (type() == nullValue) *this = Value(objectValue); CZString actualKey(key, static_cast(end - key), @@ -1192,7 +1210,7 @@ Value& Value::append(const Value& value) { return append(Value(value)); } Value& Value::append(Value&& value) { JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, - "in Json::Value::append: requires arrayValue"); + "in Json::Value::append: requires arrayValue, but found " << valueTypeToString(type())); if (type() == nullValue) { *this = Value(arrayValue); } @@ -1252,7 +1270,7 @@ bool Value::removeMember(String const& key, Value* removed) { void Value::removeMember(const char* key) { JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, - "in Json::Value::removeMember(): requires objectValue"); + "in Json::Value::removeMember(): requires objectValue, but found " << valueTypeToString(type())); if (type() == nullValue) return; @@ -1707,3 +1725,4 @@ Value& Path::make(Value& root) const { const char* version() { return JSONCPP_VERSION_STRING; } } // namespace Json + From f537efdcf9f30e1217b21a4d87fdc5bb4dc6d54a Mon Sep 17 00:00:00 2001 From: Jordan Bayles Date: Thu, 14 May 2026 16:09:20 -0700 Subject: [PATCH 2/2] style: run clang-format --- src/lib_json/json_value.cpp | 50 ++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp index 91cead17f..ac881094e 100644 --- a/src/lib_json/json_value.cpp +++ b/src/lib_json/json_value.cpp @@ -198,14 +198,22 @@ namespace Json { static const char* valueTypeToString(ValueType type) { switch (type) { - case nullValue: return "nullValue"; - case intValue: return "intValue"; - case uintValue: return "uintValue"; - case realValue: return "realValue"; - case stringValue: return "stringValue"; - case booleanValue: return "booleanValue"; - case arrayValue: return "arrayValue"; - case objectValue: return "objectValue"; + case nullValue: + return "nullValue"; + case intValue: + return "intValue"; + case uintValue: + return "uintValue"; + case realValue: + return "realValue"; + case stringValue: + return "stringValue"; + case booleanValue: + return "booleanValue"; + case arrayValue: + return "arrayValue"; + case objectValue: + return "objectValue"; } return "unknown"; } @@ -946,8 +954,10 @@ void Value::clear() { } void Value::resize(ArrayIndex newSize) { - JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, - "in Json::Value::resize(): requires arrayValue, but found " << valueTypeToString(type())); + JSON_ASSERT_MESSAGE( + type() == nullValue || type() == arrayValue, + "in Json::Value::resize(): requires arrayValue, but found " + << valueTypeToString(type())); if (type() == nullValue) *this = Value(arrayValue); ArrayIndex oldSize = size(); @@ -1080,7 +1090,8 @@ void Value::dupMeta(const Value& other) { Value& Value::resolveReference(const char* key) { JSON_ASSERT_MESSAGE( type() == nullValue || type() == objectValue, - "in Json::Value::resolveReference(): requires objectValue, but found " << valueTypeToString(type())); + "in Json::Value::resolveReference(): requires objectValue, but found " + << valueTypeToString(type())); if (type() == nullValue) *this = Value(objectValue); CZString actualKey(key, static_cast(strlen(key)), @@ -1097,9 +1108,10 @@ Value& Value::resolveReference(const char* key) { // @param key is not null-terminated. Value& Value::resolveReference(char const* key, char const* end) { - JSON_ASSERT_MESSAGE( - type() == nullValue || type() == objectValue, - "in Json::Value::resolveReference(key, end): requires objectValue, but found " << valueTypeToString(type())); + JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, + "in Json::Value::resolveReference(key, end): requires " + "objectValue, but found " + << valueTypeToString(type())); if (type() == nullValue) *this = Value(objectValue); CZString actualKey(key, static_cast(end - key), @@ -1210,7 +1222,8 @@ Value& Value::append(const Value& value) { return append(Value(value)); } Value& Value::append(Value&& value) { JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, - "in Json::Value::append: requires arrayValue, but found " << valueTypeToString(type())); + "in Json::Value::append: requires arrayValue, but found " + << valueTypeToString(type())); if (type() == nullValue) { *this = Value(arrayValue); } @@ -1269,8 +1282,10 @@ bool Value::removeMember(String const& key, Value* removed) { } void Value::removeMember(const char* key) { - JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, - "in Json::Value::removeMember(): requires objectValue, but found " << valueTypeToString(type())); + JSON_ASSERT_MESSAGE( + type() == nullValue || type() == objectValue, + "in Json::Value::removeMember(): requires objectValue, but found " + << valueTypeToString(type())); if (type() == nullValue) return; @@ -1725,4 +1740,3 @@ Value& Path::make(Value& root) const { const char* version() { return JSONCPP_VERSION_STRING; } } // namespace Json -