From 7de0b3f3c083990842523112959f8e27a0d2e5a0 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Tue, 9 Jan 2024 20:28:28 -0500 Subject: [PATCH] JSONHandler: add fallback handler support --- .idea/dictionaries/ejb.xml | 1 + libqpdf/JSONHandler.cc | 13 ++++++++++++- libqpdf/qpdf/JSONHandler.hh | 3 +++ libtests/json_handler.cc | 6 ++++++ libtests/qtest/json_handler/json_handler.out | 6 ++++++ 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/.idea/dictionaries/ejb.xml b/.idea/dictionaries/ejb.xml index 0dcc3d1a..a9dcf246 100644 --- a/.idea/dictionaries/ejb.xml +++ b/.idea/dictionaries/ejb.xml @@ -1,6 +1,7 @@ + phour whoami diff --git a/libqpdf/JSONHandler.cc b/libqpdf/JSONHandler.cc index 4a69fd60..a8116cb0 100644 --- a/libqpdf/JSONHandler.cc +++ b/libqpdf/JSONHandler.cc @@ -17,10 +17,10 @@ struct Handlers JSONHandler::void_handler_t dict_end_handler{nullptr}; JSONHandler::json_handler_t array_start_handler{nullptr}; JSONHandler::void_handler_t array_end_handler{nullptr}; - JSONHandler::void_handler_t final_handler{nullptr}; std::map> dict_handlers; std::shared_ptr fallback_dict_handler; std::shared_ptr array_item_handler; + std::shared_ptr fallback_handler; }; class JSONHandler::Members @@ -110,6 +110,12 @@ JSONHandler::addArrayHandlers( m->h.array_item_handler = ah; } +void +JSONHandler::addFallbackHandler(std::shared_ptr h) +{ + m->h.fallback_handler = std::move(h); +} + void JSONHandler::handle(std::string const& path, JSON j) { @@ -169,6 +175,11 @@ JSONHandler::handle(std::string const& path, JSON j) return; } + if (m->h.fallback_handler) { + m->h.fallback_handler->handle(path, j); + return; + } + // It would be nice to include information about what type the object was and what types were // allowed, but we're relying on schema validation to make sure input is properly structured // before calling the handlers. It would be different if this code were trying to be part of a diff --git a/libqpdf/qpdf/JSONHandler.hh b/libqpdf/qpdf/JSONHandler.hh index 9b2a0b33..1c53e32d 100644 --- a/libqpdf/qpdf/JSONHandler.hh +++ b/libqpdf/qpdf/JSONHandler.hh @@ -45,6 +45,9 @@ class JSONHandler void addArrayHandlers( json_handler_t start_fn, void_handler_t end_fn, std::shared_ptr item_handlers); + // If no handlers is called, the fallback handler will be used to try to handle the item. + void addFallbackHandler(std::shared_ptr); + // Apply handlers recursively to a JSON object. void handle(std::string const& path, JSON j); diff --git a/libtests/json_handler.cc b/libtests/json_handler.cc index 57185c98..2d3f9862 100644 --- a/libtests/json_handler.cc +++ b/libtests/json_handler.cc @@ -77,6 +77,7 @@ make_all_handler() auto h5s = std::make_shared(); h->addDictKeyHandler("five", h5s); h5s->addArrayHandlers(print_json, make_print_message("array end"), h5); + h5s->addFallbackHandler(h5); auto h6 = std::make_shared(); h6->addDictHandlers(print_json, make_print_message("dict end")); auto h6a = std::make_shared(); @@ -107,6 +108,11 @@ test_all() "five": ["x", false, "y", null, true], "phour": null, "six": {"a": {"b": "quack", "Q": "baaa"}, "b": "moo"} +})"); + h->handle(".", j); + std::cerr << "-- fallback --" << std::endl; + j = JSON::parse(R"({ + "five": "not-array" })"); h->handle(".", j); } diff --git a/libtests/qtest/json_handler/json_handler.out b/libtests/qtest/json_handler/json_handler.out index f076d4ee..4f340b85 100644 --- a/libtests/qtest/json_handler/json_handler.out +++ b/libtests/qtest/json_handler/json_handler.out @@ -63,6 +63,12 @@ .three: bool: true .two: number: 3.14 .: json: dict end +-- fallback -- +.: json: { + "five": "not-array" +} +.five: string: not-array +.: json: dict end -- errors -- bad type at top: JSON handler: value at . is not of expected type .: json: {