From 0a33f28bd43354cbea9d4c883258f9b96be1f907 Mon Sep 17 00:00:00 2001 From: Stepan Bagritsevich <43710058+BagritsevichStepan@users.noreply.github.com> Date: Sun, 4 May 2025 15:09:59 +0200 Subject: [PATCH] chore(json_family): Clean up code. FIRST PR (#5049) * chore(json_family): Clean up code Signed-off-by: Stepan Bagritsevich * refactor: address comments Signed-off-by: Stepan Bagritsevich * chore(json_family): Remove const ref for mutate operations Signed-off-by: Stepan Bagritsevich * refactor: address comments 2 Signed-off-by: Stepan Bagritsevich * chore(json_family): Remove GetJson method Signed-off-by: Stepan Bagritsevich * refactor: revert const modifiers removing Signed-off-by: Stepan Bagritsevich --------- Signed-off-by: Stepan Bagritsevich --- src/server/detail/wrapped_json_path.h | 460 ++++++++++++++------------ src/server/json_family.cc | 79 +++-- 2 files changed, 286 insertions(+), 253 deletions(-) diff --git a/src/server/detail/wrapped_json_path.h b/src/server/detail/wrapped_json_path.h index 0bf096772..694945c1b 100644 --- a/src/server/detail/wrapped_json_path.h +++ b/src/server/detail/wrapped_json_path.h @@ -21,17 +21,17 @@ using facade::OpStatus; using Nothing = std::monostate; using JsonExpression = jsoncons::jsonpath::jsonpath_expression; +namespace details { template -using JsonPathEvaluateCallback = absl::FunctionRef; +void OptionalEmplace(bool keep_defined, std::optional src, std::optional* dest); + +template void OptionalEmplace(bool keep_defined, T src, T* dest); +} // namespace details + +template +using JsonPathReadOnlyCallback = absl::FunctionRef; template struct MutateCallbackResult { - MutateCallbackResult() { - } - - MutateCallbackResult(bool should_be_deleted_, T value_) - : should_be_deleted(should_be_deleted_), value(std::move(value_)) { - } - bool should_be_deleted = false; std::optional value; }; @@ -40,6 +40,101 @@ template using JsonPathMutateCallback = absl::FunctionRef(std::optional, JsonType*)>; +enum class JsonPathType { kV2, kLegacy /*Or V1*/ }; +constexpr JsonPathType kDefaultJsonPathType = JsonPathType::kV2; + +struct CallbackResultOptions { + public: + enum class SavingOrder { kSaveFirst, kSaveLast }; + enum class OnEmpty { kSendNil, kSendWrongType }; + + // Default options for WrappedJsonPath::ExecuteReadOnlyCallback + static CallbackResultOptions DefaultReadOnlyOptions( + SavingOrder saving_order = SavingOrder::kSaveLast); + // Default options for WrappedJsonPath::ExecuteMutateCallback + static CallbackResultOptions DefaultMutateOptions(); + + OnEmpty on_empty; + SavingOrder saving_order{SavingOrder::kSaveLast}; + std::optional path_type{std::nullopt}; +}; + +template class JsonCallbackResult { + private: + template struct is_optional : std::false_type {}; + + template struct is_optional> : std::true_type {}; + + public: + using SavingOrder = CallbackResultOptions::SavingOrder; + using OnEmpty = CallbackResultOptions::OnEmpty; + + JsonCallbackResult() = default; + + explicit JsonCallbackResult(CallbackResultOptions options); + + void AddValue(T value); + + bool Empty() const; + + bool IsV1() const; + const T& AsV1() const; + const auto& AsV2() const; + + bool ShouldSendNil() const; + bool ShouldSendWrongType() const; + + private: + std::vector result_; + CallbackResultOptions options_{OnEmpty::kSendWrongType, SavingOrder::kSaveLast, + kDefaultJsonPathType}; +}; + +class WrappedJsonPath { + public: + static constexpr std::string_view kV1PathRootElement = "."; + static constexpr std::string_view kV2PathRootElement = "$"; + + WrappedJsonPath(json::Path json_path, StringOrView path, JsonPathType path_type); + + WrappedJsonPath(JsonExpression expression, StringOrView path, JsonPathType path_type); + + template + JsonCallbackResult ExecuteReadOnlyCallback(const JsonType* json_entry, + JsonPathReadOnlyCallback cb, + CallbackResultOptions options) const; + + template + OpResult>> ExecuteMutateCallback( + JsonType* json_entry, JsonPathMutateCallback cb, CallbackResultOptions options) const; + + bool IsLegacyModePath() const; + + bool RefersToRootElement() const; + + // Returns true if this is internal implementation of json path + // Check AsJsonPath + bool HoldsJsonPath() const; + + // Internal implementation of json path + const json::Path& AsJsonPath() const; + // Jsoncons implementation of json path + const JsonExpression& AsJsonExpression() const; + + // Returns the path as a string_view. + std::string_view Path() const; + + private: + CallbackResultOptions InitializePathType(CallbackResultOptions options) const; + + private: + std::variant parsed_path_; + StringOrView path_; + JsonPathType path_type_ = kDefaultJsonPathType; +}; + +// Implementation +/******************************************************************/ namespace details { template @@ -57,234 +152,177 @@ template void OptionalEmplace(bool keep_defined, T src, T* dest) { } // namespace details -enum class JsonPathType { kV2, kLegacy /*Or V1*/ }; -constexpr JsonPathType kDefaultJsonPathType = JsonPathType::kV2; +inline CallbackResultOptions CallbackResultOptions::DefaultReadOnlyOptions( + SavingOrder saving_order) { + return CallbackResultOptions{OnEmpty::kSendNil, saving_order}; +} -struct CallbackResultOptions { - public: - enum class SavingOrder { kSaveFirst, kSaveLast }; - enum class OnEmpty { kSendNil, kSendWrongType }; +inline CallbackResultOptions CallbackResultOptions::DefaultMutateOptions() { + return CallbackResultOptions{OnEmpty::kSendWrongType}; +} - // Default options for WrappedJsonPath::Evaluate - static CallbackResultOptions DefaultEvaluateOptions() { - return CallbackResultOptions{OnEmpty::kSendNil}; +template +JsonCallbackResult::JsonCallbackResult(CallbackResultOptions options) : options_(options) { +} + +template void JsonCallbackResult::AddValue(T value) { + if (result_.empty() || !IsV1()) { + result_.push_back(std::move(value)); + return; } - static CallbackResultOptions DefaultEvaluateOptions(SavingOrder saving_order) { - return {saving_order, OnEmpty::kSendNil}; + details::OptionalEmplace(options_.saving_order == SavingOrder::kSaveFirst, std::move(value), + &result_.front()); +} + +template bool JsonCallbackResult::Empty() const { + return result_.empty(); +} + +template bool JsonCallbackResult::IsV1() const { + return options_.path_type == JsonPathType::kLegacy; +} + +template const T& JsonCallbackResult::AsV1() const { + return result_.front(); +} + +template const auto& JsonCallbackResult::AsV2() const { + return result_; +} + +template bool JsonCallbackResult::ShouldSendNil() const { + return IsV1() && options_.on_empty == OnEmpty::kSendNil && result_.empty(); +} + +template bool JsonCallbackResult::ShouldSendWrongType() const { + if (IsV1()) { + if (result_.empty() && options_.on_empty == OnEmpty::kSendWrongType) + return true; + + if constexpr (is_optional::value) { + return !result_.front().has_value(); + } + } + return false; +} + +inline WrappedJsonPath::WrappedJsonPath(json::Path json_path, StringOrView path, + JsonPathType path_type) + : parsed_path_(std::move(json_path)), path_(std::move(path)), path_type_(path_type) { +} + +inline WrappedJsonPath::WrappedJsonPath(JsonExpression expression, StringOrView path, + JsonPathType path_type) + : parsed_path_(std::move(expression)), path_(std::move(path)), path_type_(path_type) { +} + +template +JsonCallbackResult WrappedJsonPath::ExecuteReadOnlyCallback( + const JsonType* json_entry, JsonPathReadOnlyCallback cb, + CallbackResultOptions options) const { + JsonCallbackResult read_result{InitializePathType(options)}; + + auto eval_callback = [&cb, &read_result](std::string_view path, const JsonType& val) { + read_result.AddValue(cb(path, val)); + }; + + if (HoldsJsonPath()) { + const auto& json_path = AsJsonPath(); + json::EvaluatePath(json_path, *json_entry, + [&eval_callback](std::optional key, const JsonType& val) { + eval_callback(key ? *key : std::string_view{}, val); + }); + } else { + const auto& json_expression = AsJsonExpression(); + json_expression.evaluate(*json_entry, eval_callback); } - // Default options for WrappedJsonPath::Mutate - static CallbackResultOptions DefaultMutateOptions() { - return CallbackResultOptions{OnEmpty::kSendWrongType}; - } + return read_result; +} - explicit CallbackResultOptions(OnEmpty on_empty_) : on_empty(on_empty_) { - } +template +OpResult>> WrappedJsonPath::ExecuteMutateCallback( + JsonType* json_entry, JsonPathMutateCallback cb, CallbackResultOptions options) const { + JsonCallbackResult> mutate_result{InitializePathType(options)}; - CallbackResultOptions(JsonPathType path_type_, SavingOrder saving_order_, OnEmpty on_empty_) - : path_type(path_type_), saving_order(saving_order_), on_empty(on_empty_) { - } + auto mutate_callback = [&cb, &mutate_result](std::optional path, + JsonType* val) -> bool { + auto res = cb(path, val); + if (res.value.has_value()) { + mutate_result.AddValue(std::move(res.value).value()); + } else if (!mutate_result.IsV1()) { + mutate_result.AddValue(std::nullopt); + } + return res.should_be_deleted; + }; - std::optional path_type; - SavingOrder saving_order{SavingOrder::kSaveLast}; - OnEmpty on_empty; + if (HoldsJsonPath()) { + const auto& json_path = AsJsonPath(); + json::MutatePath(json_path, mutate_callback, json_entry); + } else { + using namespace jsoncons::jsonpath; + using namespace jsoncons::jsonpath::detail; + using Evaluator = jsonpath_evaluator; + using ValueType = Evaluator::value_type; + using Reference = Evaluator::reference; + using JsonSelector = Evaluator::path_expression_type; - private: - CallbackResultOptions(SavingOrder saving_order_, OnEmpty on_empty_) - : saving_order(saving_order_), on_empty(on_empty_) { - } -}; + custom_functions funcs = custom_functions(); -template class JsonCallbackResult { - template struct is_optional : std::false_type {}; + std::error_code ec; + static_resources static_resources(funcs); + Evaluator e; - template struct is_optional> : std::true_type {}; - - public: - using SavingOrder = CallbackResultOptions::SavingOrder; - using OnEmpty = CallbackResultOptions::OnEmpty; - - JsonCallbackResult() - : options_(kDefaultJsonPathType, SavingOrder::kSaveLast, OnEmpty::kSendWrongType) { - } - - explicit JsonCallbackResult(CallbackResultOptions options) : options_(options) { - } - - void AddValue(T value) { - if (result_.empty() || !IsV1()) { - result_.push_back(std::move(value)); - return; + JsonSelector expr = e.compile(static_resources, path_.view(), ec); + if (ec) { + VLOG(1) << "Failed to mutate json with error: " << ec.message(); + return OpStatus::SYNTAX_ERR; } - details::OptionalEmplace(options_.saving_order == SavingOrder::kSaveFirst, std::move(value), - &result_.front()); - } + dynamic_resources resources; - bool IsV1() const { - return options_.path_type == JsonPathType::kLegacy; - } - - const T& AsV1() const { - return result_.front(); - } - - const auto& AsV2() const { - return result_; - } - - bool Empty() const { - return result_.empty(); - } - - bool ShouldSendNil() const { - return IsV1() && options_.on_empty == OnEmpty::kSendNil && result_.empty(); - } - - bool ShouldSendWrongType() const { - if (IsV1()) { - if (result_.empty() && options_.on_empty == OnEmpty::kSendWrongType) - return true; - - if constexpr (is_optional::value) { - return !result_.front().has_value(); - } - } - return false; - } - - private: - std::vector result_; - CallbackResultOptions options_; -}; - -class WrappedJsonPath { - public: - static constexpr std::string_view kV1PathRootElement = "."; - static constexpr std::string_view kV2PathRootElement = "$"; - - WrappedJsonPath(json::Path json_path, StringOrView path, JsonPathType path_type) - : parsed_path_(std::move(json_path)), path_(std::move(path)), path_type_(path_type) { - } - - WrappedJsonPath(JsonExpression expression, StringOrView path, JsonPathType path_type) - : parsed_path_(std::move(expression)), path_(std::move(path)), path_type_(path_type) { - } - - template - JsonCallbackResult Evaluate(const JsonType* json_entry, JsonPathEvaluateCallback cb, - CallbackResultOptions options) const { - JsonCallbackResult eval_result{InitializePathType(options)}; - - auto eval_callback = [&cb, &eval_result](std::string_view path, const JsonType& val) { - eval_result.AddValue(cb(path, val)); + auto f = [&mutate_callback](const basic_path_node& path, JsonType& val) { + mutate_callback(to_string(path), &val); }; - if (HoldsJsonPath()) { - const auto& json_path = AsJsonPath(); - json::EvaluatePath( - json_path, *json_entry, - [&eval_callback](std::optional key, const JsonType& val) { - eval_callback(key ? *key : std::string_view{}, val); - }); - } else { - const auto& json_expression = AsJsonExpression(); - json_expression.evaluate(*json_entry, eval_callback); - } - - return eval_result; + expr.evaluate(resources, *json_entry, JsonSelector::path_node_type{}, *json_entry, std::move(f), + result_options::nodups | result_options::path); } + return mutate_result; +} - template - OpResult>> Mutate(JsonType* json_entry, - JsonPathMutateCallback cb, - CallbackResultOptions options) const { - JsonCallbackResult> mutate_result{InitializePathType(options)}; +inline bool WrappedJsonPath::IsLegacyModePath() const { + return path_type_ == JsonPathType::kLegacy; +} - auto mutate_callback = [&cb, &mutate_result](std::optional path, - JsonType* val) -> bool { - auto res = cb(path, val); - if (res.value.has_value()) { - mutate_result.AddValue(std::move(res.value).value()); - } else if (!mutate_result.IsV1()) { - mutate_result.AddValue(std::nullopt); - } - return res.should_be_deleted; - }; +inline bool WrappedJsonPath::RefersToRootElement() const { + auto path = path_.view(); + return path.empty() || path == kV1PathRootElement || path == kV2PathRootElement; +} - if (HoldsJsonPath()) { - const auto& json_path = AsJsonPath(); - json::MutatePath(json_path, mutate_callback, json_entry); - } else { - using namespace jsoncons::jsonpath; - using namespace jsoncons::jsonpath::detail; - using Evaluator = jsonpath_evaluator; - using ValueType = Evaluator::value_type; - using Reference = Evaluator::reference; - using JsonSelector = Evaluator::path_expression_type; +inline bool WrappedJsonPath::HoldsJsonPath() const { + return std::holds_alternative(parsed_path_); +} - custom_functions funcs = custom_functions(); +inline const json::Path& WrappedJsonPath::AsJsonPath() const { + return std::get(parsed_path_); +} - std::error_code ec; - static_resources static_resources(funcs); - Evaluator e; +inline const JsonExpression& WrappedJsonPath::AsJsonExpression() const { + return std::get(parsed_path_); +} - JsonSelector expr = e.compile(static_resources, path_.view(), ec); - if (ec) { - VLOG(1) << "Failed to mutate json with error: " << ec.message(); - return OpStatus::SYNTAX_ERR; - } +inline std::string_view WrappedJsonPath::Path() const { + return path_.view(); +} - dynamic_resources resources; - - auto f = [&mutate_callback](const basic_path_node& path, JsonType& val) { - mutate_callback(to_string(path), &val); - }; - - expr.evaluate(resources, *json_entry, JsonSelector::path_node_type{}, *json_entry, - std::move(f), result_options::nodups | result_options::path); - } - return mutate_result; +inline CallbackResultOptions WrappedJsonPath::InitializePathType( + CallbackResultOptions options) const { + if (!options.path_type) { + options.path_type = path_type_; } - - bool IsLegacyModePath() const { - return path_type_ == JsonPathType::kLegacy; - } - - bool RefersToRootElement() const { - auto path = path_.view(); - return path.empty() || path == kV1PathRootElement || path == kV2PathRootElement; - } - - bool HoldsJsonPath() const { - return std::holds_alternative(parsed_path_); - } - - const json::Path& AsJsonPath() const { - return std::get(parsed_path_); - } - - const JsonExpression& AsJsonExpression() const { - return std::get(parsed_path_); - } - - std::string_view Path() const { - return path_.view(); - } - - private: - CallbackResultOptions InitializePathType(CallbackResultOptions options) const { - if (!options.path_type) { - options.path_type = path_type_; - } - return options; - } - - private: - std::variant parsed_path_; - StringOrView path_; - JsonPathType path_type_ = kDefaultJsonPathType; -}; + return options; +} } // namespace dfly diff --git a/src/server/json_family.cc b/src/server/json_family.cc index 19b634cf5..ac9f2271e 100644 --- a/src/server/json_family.cc +++ b/src/server/json_family.cc @@ -404,17 +404,6 @@ string JsonTypeToName(const JsonType& val) { return std::string{}; } -OpResult GetJson(const OpArgs& op_args, string_view key) { - auto it_res = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_JSON); - if (!it_res.ok()) - return it_res.status(); - - JsonType* json_val = it_res.value()->second.GetJson(); - DCHECK(json_val) << "should have a valid JSON object for key " << key; - - return json_val; -} - // Returns the index of the next right bracket OptSize GetNextIndex(string_view str) { size_t current_idx = 0; @@ -593,25 +582,31 @@ size_t CountJsonFields(const JsonType& j) { return res; } -struct EvaluateOperationOptions { +struct ReadOnlyOperationOptions { bool return_nil_if_key_not_found = false; - CallbackResultOptions cb_result_options = CallbackResultOptions::DefaultEvaluateOptions(); + CallbackResultOptions cb_result_options = CallbackResultOptions::DefaultReadOnlyOptions(); }; template -OpResult> JsonEvaluateOperation(const OpArgs& op_args, std::string_view key, +OpResult> JsonReadOnlyOperation(const OpArgs& op_args, std::string_view key, const WrappedJsonPath& json_path, - JsonPathEvaluateCallback cb, - EvaluateOperationOptions options = {}) { - OpResult result = GetJson(op_args, key); - if (options.return_nil_if_key_not_found && result == OpStatus::KEY_NOTFOUND) { - return JsonCallbackResult{ - {JsonPathType::kLegacy, options.cb_result_options.saving_order, - CallbackResultOptions::OnEmpty::kSendNil}}; // set legacy mode to return nil + JsonPathReadOnlyCallback cb, + ReadOnlyOperationOptions options = {}) { + auto it_res = op_args.GetDbSlice().FindReadOnly(op_args.db_cntx, key, OBJ_JSON); + + if (!it_res) { + if (options.return_nil_if_key_not_found && it_res == OpStatus::KEY_NOTFOUND) { + return JsonCallbackResult{{CallbackResultOptions::OnEmpty::kSendNil, + options.cb_result_options.saving_order, + JsonPathType::kLegacy}}; // set legacy mode to return nil + } + return it_res.status(); } - RETURN_ON_BAD_STATUS(result); - return json_path.Evaluate(*result, cb, options.cb_result_options); + JsonType* json_val = it_res.value()->second.GetJson(); + DCHECK(json_val) << "should have a valid JSON object for key " << key; + + return json_path.ExecuteReadOnlyCallback(json_val, cb, options.cb_result_options); } struct MutateOperationOptions { @@ -640,7 +635,7 @@ OpResult>> JsonMutateOperation(const OpArgs& op_a op_args.shard->search_indices()->RemoveDoc(key, op_args.db_cntx, pv); - auto mutate_res = json_path.Mutate(json_val, cb, options.cb_result_options); + auto mutate_res = json_path.ExecuteMutateCallback(json_val, cb, options.cb_result_options); // Call post mutate callback if (mutate_res && options.post_mutate_cb) { @@ -719,11 +714,11 @@ OpResult OpJsonGet(const OpArgs& op_args, string_view key, auto cb = [](std::string_view, const JsonType& val) { return val; }; const bool legacy_mode_is_enabled = LegacyModeIsEnabled(paths); - CallbackResultOptions cb_options = CallbackResultOptions::DefaultEvaluateOptions(); + CallbackResultOptions cb_options = CallbackResultOptions::DefaultReadOnlyOptions(); cb_options.path_type = legacy_mode_is_enabled ? JsonPathType::kLegacy : JsonPathType::kV2; auto eval_wrapped = [&](const WrappedJsonPath& json_path) -> std::optional { - auto eval_result = json_path.Evaluate(&json_entry, cb, cb_options); + auto eval_result = json_path.ExecuteReadOnlyCallback(&json_entry, cb, cb_options); DCHECK(legacy_mode_is_enabled == eval_result.IsV1()); @@ -764,7 +759,7 @@ auto OpType(const OpArgs& op_args, string_view key, const WrappedJsonPath& json_ auto cb = [](const string_view&, const JsonType& val) -> std::string { return JsonTypeToName(val); }; - return JsonEvaluateOperation(op_args, key, json_path, std::move(cb), {true}); + return JsonReadOnlyOperation(op_args, key, json_path, std::move(cb), {true}); } OpResult> OpStrLen(const OpArgs& op_args, string_view key, @@ -776,9 +771,9 @@ OpResult> OpStrLen(const OpArgs& op_args, string_vie return nullopt; } }; - return JsonEvaluateOperation( + return JsonReadOnlyOperation( op_args, key, json_path, std::move(cb), - {true, CallbackResultOptions::DefaultEvaluateOptions(SavingOrder::kSaveFirst)}); + {true, CallbackResultOptions::DefaultReadOnlyOptions(SavingOrder::kSaveFirst)}); } OpResult> OpObjLen(const OpArgs& op_args, string_view key, @@ -790,10 +785,10 @@ OpResult> OpObjLen(const OpArgs& op_args, string_vie return nullopt; } }; - return JsonEvaluateOperation( + return JsonReadOnlyOperation( op_args, key, json_path, std::move(cb), {json_path.IsLegacyModePath(), - CallbackResultOptions::DefaultEvaluateOptions(SavingOrder::kSaveFirst)}); + CallbackResultOptions::DefaultReadOnlyOptions(SavingOrder::kSaveFirst)}); } OpResult> OpArrLen(const OpArgs& op_args, string_view key, @@ -805,9 +800,9 @@ OpResult> OpArrLen(const OpArgs& op_args, string_vie return std::nullopt; } }; - return JsonEvaluateOperation( + return JsonReadOnlyOperation( op_args, key, json_path, std::move(cb), - {true, CallbackResultOptions::DefaultEvaluateOptions(SavingOrder::kSaveFirst)}); + {true, CallbackResultOptions::DefaultReadOnlyOptions(SavingOrder::kSaveFirst)}); } template @@ -973,8 +968,8 @@ OpResult OpDel(const OpArgs& op_args, string_view key, string_view path, return {}; }; - auto res = json_path.Mutate(json_val, std::move(cb), - CallbackResultOptions::DefaultMutateOptions()); + auto res = json_path.ExecuteMutateCallback( + json_val, std::move(cb), CallbackResultOptions::DefaultMutateOptions()); RETURN_ON_BAD_STATUS(res); if (deletion_items.empty()) { @@ -1017,10 +1012,10 @@ auto OpObjKeys(const OpArgs& op_args, string_view key, const WrappedJsonPath& js } return vec; }; - return JsonEvaluateOperation( + return JsonReadOnlyOperation( op_args, key, json_path, std::move(cb), {json_path.IsLegacyModePath(), - CallbackResultOptions::DefaultEvaluateOptions(SavingOrder::kSaveFirst)}); + CallbackResultOptions::DefaultReadOnlyOptions(SavingOrder::kSaveFirst)}); } OpResult> OpStrAppend(const OpArgs& op_args, string_view key, @@ -1243,7 +1238,7 @@ auto OpArrIndex(const OpArgs& op_args, string_view key, const WrappedJsonPath& j return pos; }; - return JsonEvaluateOperation>( + return JsonReadOnlyOperation>( op_args, key, json_path, std::move(cb), {false, CallbackResultOptions{CallbackResultOptions::OnEmpty::kSendWrongType}}); } @@ -1270,8 +1265,8 @@ std::vector> OpJsonMGet(const WrappedJsonPath& json_p auto eval_wrapped = [&json_val, &cb](const WrappedJsonPath& json_path) -> std::optional { - auto eval_result = json_path.Evaluate( - json_val, std::move(cb), CallbackResultOptions::DefaultEvaluateOptions()); + auto eval_result = json_path.ExecuteReadOnlyCallback( + json_val, std::move(cb), CallbackResultOptions::DefaultReadOnlyOptions()); if (eval_result.IsV1()) { if (eval_result.Empty()) @@ -1306,13 +1301,13 @@ auto OpFields(const OpArgs& op_args, string_view key, const WrappedJsonPath& jso auto cb = [](const string_view&, const JsonType& val) -> std::optional { return CountJsonFields(val); }; - return JsonEvaluateOperation>(op_args, key, json_path, std::move(cb)); + return JsonReadOnlyOperation>(op_args, key, json_path, std::move(cb)); } // Returns json vector that represents the result of the json query. auto OpResp(const OpArgs& op_args, string_view key, const WrappedJsonPath& json_path) { auto cb = [](const string_view&, const JsonType& val) { return val; }; - return JsonEvaluateOperation(op_args, key, json_path, std::move(cb)); + return JsonReadOnlyOperation(op_args, key, json_path, std::move(cb)); } // Returns boolean that represents the result of the operation.