From 74931bd02aa753471086be3ed036cd3eb6585001 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Mon, 27 Nov 2023 11:08:47 +0100 Subject: [PATCH] error-messages: Numeric limit errors should show maximum precision Fixes #255 --- src/json-validator.cpp | 19 ++++++--- test/CMakeLists.txt | 4 ++ ...ssue-255-error-message-limit-precision.cpp | 41 +++++++++++++++++++ 3 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 test/issue-255-error-message-limit-precision.cpp diff --git a/src/json-validator.cpp b/src/json-validator.cpp index 1fd0de1..95ec8b7 100644 --- a/src/json-validator.cpp +++ b/src/json-validator.cpp @@ -877,22 +877,31 @@ class numeric : public schema { T value = instance; // conversion of json to value_type + std::ostringstream oss; + if (multipleOf_.first && value != 0) // zero is multiple of everything if (violates_multiple_of(value)) - e.error(ptr, instance, "instance is not a multiple of " + std::to_string(multipleOf_.second)); + oss << "instance is not a multiple of " << json(multipleOf_.second); if (maximum_.first) { if (exclusiveMaximum_ && value >= maximum_.second) - e.error(ptr, instance, "instance exceeds or equals maximum of " + std::to_string(maximum_.second)); + oss << "instance exceeds or equals maximum of " << json(maximum_.second); else if (value > maximum_.second) - e.error(ptr, instance, "instance exceeds maximum of " + std::to_string(maximum_.second)); + oss << "instance exceeds maximum of " << json(maximum_.second); } if (minimum_.first) { if (exclusiveMinimum_ && value <= minimum_.second) - e.error(ptr, instance, "instance is below or equals minimum of " + std::to_string(minimum_.second)); + oss << "instance is below or equals minimum of " << json(minimum_.second); else if (value < minimum_.second) - e.error(ptr, instance, "instance is below minimum of " + std::to_string(minimum_.second)); + oss << "instance is below minimum of " << json(minimum_.second); + } + + oss.seekp(0, std::ios::end); + auto size = oss.tellp(); + if (size != 0) { + oss.seekp(0, std::ios::beg); + e.error(ptr, instance, oss.str()); } } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b461df6..50ba0e6 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -85,3 +85,7 @@ add_test(NAME issue-229-oneof-default-values COMMAND issue-229-oneof-default-val add_executable(issue-243-root-default-values issue-243-root-default-values.cpp) target_link_libraries(issue-243-root-default-values nlohmann_json_schema_validator) add_test(NAME issue-243-root-default-values COMMAND issue-243-root-default-values) + +add_executable(issue-255-error-message-limit-precision issue-255-error-message-limit-precision.cpp) +target_link_libraries(issue-255-error-message-limit-precision nlohmann_json_schema_validator) +add_test(NAME issue-255-error-message-limit-precision COMMAND issue-255-error-message-limit-precision) diff --git a/test/issue-255-error-message-limit-precision.cpp b/test/issue-255-error-message-limit-precision.cpp new file mode 100644 index 0000000..6b47995 --- /dev/null +++ b/test/issue-255-error-message-limit-precision.cpp @@ -0,0 +1,41 @@ +#include +#include + +using nlohmann::json; +using nlohmann::json_schema::json_validator; + +static const json schema = R"( +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "arc.schema.json", + "properties": { + "angle": { + "type": "number", + "description": "Radians, from -π to π.", + "minimum": -3.14159265358979323846, + "maximum": 3.14159265358979323846 + } + } +})"_json; + +class custom_error_handler : public nlohmann::json_schema::basic_error_handler +{ + void error(const nlohmann::json::json_pointer &ptr, const json &instance, const std::string &message) override + { + if (message != "instance exceeds maximum of 3.141592653589793") + throw std::invalid_argument("Precision print does not work."); + } +}; + +int main(void) +{ + json_validator validator; + + auto instance = R"({ "angle": 3.1415927410125732 })"_json; + + validator.set_root_schema(schema); + custom_error_handler err; + validator.validate(instance, err); + + return 0; +}