From 442359f5bf3563ecf765e3eb51c52fec06be1e25 Mon Sep 17 00:00:00 2001 From: Martchus Date: Sat, 29 Feb 2020 22:35:02 +0100 Subject: [PATCH] Add a function to format JSON deserialization errors --- lib/CMakeLists.txt | 7 +++- lib/json/errorformatting.h | 78 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 lib/json/errorformatting.h diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index ce6b8dc..c4ec92f 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -21,7 +21,8 @@ if (RapidJSON_FOUND) json/reflector-boosthana.h json/reflector-chronoutilities.h json/serializable.h - json/errorhandling.h) + json/errorhandling.h + json/errorformatting.h) list(APPEND TEST_SRC_FILES tests/jsonreflector.cpp tests/jsonreflector-boosthana.cpp tests/jsonreflector-chronoutilities.cpp) endif () @@ -53,4 +54,6 @@ include(Doxygen) include(ConfigHeader) # export target name so the generator can link against it -set(${META_PROJECT_VARNAME_UPPER}_TARGET_NAME "${META_TARGET_NAME}" PARENT_SCOPE) +set(${META_PROJECT_VARNAME_UPPER}_TARGET_NAME + "${META_TARGET_NAME}" + PARENT_SCOPE) diff --git a/lib/json/errorformatting.h b/lib/json/errorformatting.h new file mode 100644 index 0000000..33e5fe1 --- /dev/null +++ b/lib/json/errorformatting.h @@ -0,0 +1,78 @@ +#ifndef REFLECTIVE_RAPIDJSON_JSON_ERROR_FORMATTING_H +#define REFLECTIVE_RAPIDJSON_JSON_ERROR_FORMATTING_H + +/*! + * \file errorformatting.h + * \brief Contains helper functions to format errors when deserializing JSON files. + */ + +#include "./errorhandling.h" + +#include + +#include + +namespace ReflectiveRapidJSON { + +inline std::string_view jsonTypeToString(JsonType jsonType) +{ + switch (jsonType) { + case ReflectiveRapidJSON::JsonType::Null: + return "null"; + case ReflectiveRapidJSON::JsonType::Number: + return "number"; + case ReflectiveRapidJSON::JsonType::Bool: + return "bool"; + case ReflectiveRapidJSON::JsonType::String: + return "string"; + case ReflectiveRapidJSON::JsonType::Array: + return "array"; + case ReflectiveRapidJSON::JsonType::Object: + return "object"; + default: + return "?"; + } +} + +inline std::string formatJsonDeserializationError(const JsonDeserializationError &error) +{ + using namespace CppUtilities; + std::string_view errorKind; + std::string additionalInfo; + switch (error.kind) { + case JsonDeserializationErrorKind::TypeMismatch: + errorKind = "type mismatch"; + additionalInfo = ": expected \"" % jsonTypeToString(error.expectedType) % "\", got \"" % jsonTypeToString(error.actualType) + '\"'; + break; + case JsonDeserializationErrorKind::ArraySizeMismatch: + errorKind = "array size mismatch"; + break; + case JsonDeserializationErrorKind::ConversionError: + errorKind = "conversion error"; + break; + case JsonDeserializationErrorKind::UnexpectedDuplicate: + errorKind = "unexpected duplicate"; + break; + case JsonDeserializationErrorKind::InvalidVariantObject: + errorKind = "invalid variant object"; + break; + case JsonDeserializationErrorKind::InvalidVariantIndex: + errorKind = "invalid variant index"; + break; + default: + errorKind = "semantic error"; + } + if (error.record && error.member) { + return errorKind % " within record \"" % error.record % "\" and member \"" % error.member % '\"' + additionalInfo; + } else if (error.record && error.index != JsonDeserializationError::noIndex) { + return errorKind % " within record \"" % error.record % "\" and index \"" % error.index % '\"' + additionalInfo; + } else if (error.record) { + return errorKind % " within record \"" % error.record % '\"' + additionalInfo; + } else { + return errorKind % " in document" + additionalInfo; + } +} + +} // namespace ReflectiveRapidJSON + +#endif // REFLECTIVE_RAPIDJSON_JSON_ERROR_FORMATTING_H