File: json_query.hpp

package info (click to toggle)
jsoncons 1.3.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 17,584 kB
  • sloc: cpp: 136,382; sh: 33; makefile: 5
file content (225 lines) | stat: -rw-r--r-- 11,715 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
// Copyright 2013-2025 Daniel Parker
// Distributed under the Boost license, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

// See https://github.com/danielaparker/jsoncons for latest version

#ifndef JSONCONS_EXT_JSONPATH_JSON_QUERY_HPP
#define JSONCONS_EXT_JSONPATH_JSON_QUERY_HPP

#include <type_traits>

#include <jsoncons/allocator_set.hpp>
#include <jsoncons/json_type_traits.hpp>
#include <jsoncons/tag_type.hpp>
#include <jsoncons/utility/extension_traits.hpp>

#include <jsoncons_ext/jsonpath/token_evaluator.hpp>
#include <jsoncons_ext/jsonpath/jsonpath_expression.hpp>
#include <jsoncons_ext/jsonpath/jsonpath_parser.hpp>
#include <jsoncons_ext/jsonpath/path_node.hpp>

namespace jsoncons { 
namespace jsonpath {

    template <typename Json,typename JsonReference = const Json&>
    struct legacy_jsonpath_traits
    {
        using char_type = typename Json::char_type;
        using string_type = typename Json::string_type;
        using string_view_type = typename Json::string_view_type;
        using element_type = Json;
        using value_type = typename std::remove_cv<Json>::type;
        using reference = JsonReference;
        using const_reference = const value_type&;
        using pointer = typename std::conditional<std::is_const<typename std::remove_reference<reference>::type>::value,typename Json::const_pointer,typename Json::pointer>::type;
        using allocator_type = typename value_type::allocator_type;
        using evaluator_type = typename jsoncons::jsonpath::detail::jsonpath_evaluator<value_type, reference>;
        using path_node_type = basic_path_node<typename Json::char_type>;
        using path_expression_type = jsoncons::jsonpath::detail::path_expression<value_type,reference>;
        using path_pointer = const path_node_type*;
    };
     
    template <typename Json>
    Json json_query(const Json& root,
                    const typename Json::string_view_type& path, 
                    result_options options = result_options(),
                    const custom_functions<Json>& functions = custom_functions<Json>())
    {
        auto expr = make_expression<Json>(path, functions);
        return expr.evaluate(root, options);
    }

    template <typename Json,typename Callback>
    typename std::enable_if<extension_traits::is_binary_function_object<Callback,const typename Json::string_type&,const Json&>::value,void>::type
    json_query(const Json& root, 
               const typename Json::string_view_type& path, 
               Callback callback,
               result_options options = result_options(),
               const custom_functions<Json>& functions = custom_functions<Json>())
    {
        auto expr = make_expression<Json>(path, functions);
        expr.evaluate(root, callback, options);
    }

    template <typename Json,typename TempAllocator >
    Json json_query(const allocator_set<typename Json::allocator_type,TempAllocator>& alloc_set, 
        const Json& root, const typename Json::string_view_type& path, 
        result_options options = result_options(),
        const custom_functions<Json>& functions = custom_functions<Json>())
    {
        auto expr = make_expression<Json>(alloc_set, path, functions);
        return expr.evaluate(root, options);
    }

    template <typename Json,typename Callback,typename TempAllocator >
    typename std::enable_if<extension_traits::is_binary_function_object<Callback,const typename Json::string_type&,const Json&>::value,void>::type
    json_query(const allocator_set<typename Json::allocator_type,TempAllocator>& alloc_set, 
        const Json& root, const typename Json::string_view_type& path, 
        Callback callback,
        result_options options = result_options(),
        const custom_functions<Json>& functions = custom_functions<Json>())
    {
        auto expr = make_expression<Json>(alloc_set, path, functions);
        expr.evaluate(root, callback, options);
    }

    template <typename Json,typename T>
    typename std::enable_if<is_json_type_traits_specialized<Json,T>::value,void>::type
        json_replace(Json& root, const typename Json::string_view_type& path, T&& new_value,
                     const custom_functions<Json>& funcs = custom_functions<Json>())
    {
        using jsonpath_traits_type = jsoncons::jsonpath::legacy_jsonpath_traits<Json, Json&>;

        using value_type = typename jsonpath_traits_type::value_type;
        using reference = typename jsonpath_traits_type::reference;
        using evaluator_type = typename jsonpath_traits_type::evaluator_type;
        using path_expression_type = typename jsonpath_traits_type::path_expression_type;
        using path_node_type = typename jsonpath_traits_type::path_node_type;

        auto resources = jsoncons::make_unique<jsoncons::jsonpath::detail::static_resources<value_type>>(funcs);
        evaluator_type evaluator;
        path_expression_type expr = evaluator.compile(*resources, path);

        jsoncons::jsonpath::detail::eval_context<Json,reference> context;
        auto callback = [&new_value](const path_node_type&, reference v)
        {
            v = std::forward<T>(new_value);
        };

        result_options options = result_options::nodups | result_options::path | result_options::sort_descending;
        expr.evaluate(context, root, path_node_type{}, root, callback, options);
    }

    template <typename Json,typename T,typename TempAllocator >
    typename std::enable_if<is_json_type_traits_specialized<Json,T>::value,void>::type
        json_replace(const allocator_set<typename Json::allocator_type,TempAllocator>& alloc_set, 
            Json& root, const typename Json::string_view_type& path, T&& new_value,
            const custom_functions<Json>& funcs = custom_functions<Json>())
    {
        using jsonpath_traits_type = jsoncons::jsonpath::legacy_jsonpath_traits<Json, Json&>;

        using value_type = typename jsonpath_traits_type::value_type;
        using reference = typename jsonpath_traits_type::reference;
        using evaluator_type = typename jsonpath_traits_type::evaluator_type;
        using path_expression_type = typename jsonpath_traits_type::path_expression_type;
        using path_node_type = typename jsonpath_traits_type::path_node_type;

        auto resources = jsoncons::make_unique<jsoncons::jsonpath::detail::static_resources<value_type>>(funcs, alloc_set.get_allocator());
        evaluator_type evaluator{alloc_set.get_allocator()};
        path_expression_type expr = evaluator.compile(*resources, path);

        jsoncons::jsonpath::detail::eval_context<Json,reference> context{alloc_set.get_allocator()};
        auto callback = [&new_value](const path_node_type&, reference v)
        {
            v = Json(std::forward<T>(new_value), semantic_tag::none);
        };
        result_options options = result_options::nodups | result_options::path | result_options::sort_descending;
        expr.evaluate(context, root, path_node_type{}, root, callback, options);
    }

    template <typename Json,typename BinaryCallback>
    typename std::enable_if<extension_traits::is_binary_function_object<BinaryCallback,const typename Json::string_type&,Json&>::value,void>::type
    json_replace(Json& root, const typename Json::string_view_type& path , BinaryCallback callback, 
                 const custom_functions<Json>& funcs = custom_functions<Json>())
    {
        using jsonpath_traits_type = jsoncons::jsonpath::legacy_jsonpath_traits<Json, Json&>;

        using value_type = typename jsonpath_traits_type::value_type;
        using reference = typename jsonpath_traits_type::reference;
        using evaluator_type = typename jsonpath_traits_type::evaluator_type;
        using path_expression_type = typename jsonpath_traits_type::path_expression_type;
        using path_node_type = typename jsonpath_traits_type::path_node_type;

        auto resources = jsoncons::make_unique<jsoncons::jsonpath::detail::static_resources<value_type>>(funcs);
        evaluator_type evaluator;
        path_expression_type expr = evaluator.compile(*resources, path);

        jsoncons::jsonpath::detail::eval_context<Json,reference> context;

        auto f = [&callback](const path_node_type& path, reference val)
        {
            callback(to_basic_string(path), val);
        };
        result_options options = result_options::nodups | result_options::path | result_options::sort_descending;
        expr.evaluate(context, root, path_node_type{}, root, f, options);
    }

    template <typename Json,typename BinaryCallback,typename TempAllocator >
    typename std::enable_if<extension_traits::is_binary_function_object<BinaryCallback,const typename Json::string_type&,Json&>::value,void>::type
    json_replace(const allocator_set<typename Json::allocator_type,TempAllocator>& alloc_set, 
        Json& root, const typename Json::string_view_type& path , BinaryCallback callback, 
        const custom_functions<Json>& funcs = custom_functions<Json>())
    {
        using jsonpath_traits_type = jsoncons::jsonpath::legacy_jsonpath_traits<Json, Json&>;

        using value_type = typename jsonpath_traits_type::value_type;
        using reference = typename jsonpath_traits_type::reference;
        using evaluator_type = typename jsonpath_traits_type::evaluator_type;
        using path_expression_type = typename jsonpath_traits_type::path_expression_type;
        using path_node_type = typename jsonpath_traits_type::path_node_type;

        auto resources = jsoncons::make_unique<jsoncons::jsonpath::detail::static_resources<value_type>>(funcs, alloc_set.get_allocator());
        evaluator_type evaluator{alloc_set.get_allocator()};
        path_expression_type expr = evaluator.compile(*resources, path);

        jsoncons::jsonpath::detail::eval_context<Json,reference> context{alloc_set.get_allocator()};

        auto f = [&callback](const path_node_type& path, reference val)
        {
            callback(to_basic_string(path), val);
        };
        result_options options = result_options::nodups | result_options::path | result_options::sort_descending;
        expr.evaluate(context, root, path_node_type{}, root, f, options);
    }

    // Legacy replace function
    template <typename Json,typename UnaryCallback>
    typename std::enable_if<extension_traits::is_unary_function_object<UnaryCallback,Json>::value,void>::type
    json_replace(Json& root, const typename Json::string_view_type& path , UnaryCallback callback)
    {
        using jsonpath_traits_type = jsoncons::jsonpath::legacy_jsonpath_traits<Json, Json&>;

        using value_type = typename jsonpath_traits_type::value_type;
        using reference = typename jsonpath_traits_type::reference;
        using evaluator_type = typename jsonpath_traits_type::evaluator_type;
        using path_expression_type = typename jsonpath_traits_type::path_expression_type;
        using path_node_type = typename jsonpath_traits_type::path_node_type;

        auto resources = jsoncons::make_unique<jsoncons::jsonpath::detail::static_resources<value_type>>();
        evaluator_type evaluator;
        path_expression_type expr = evaluator.compile(*resources, path);

        jsoncons::jsonpath::detail::eval_context<Json,reference> context;
        auto f = [callback](const path_node_type&, reference v)
        {
            v = callback(v);
        };
        result_options options = result_options::nodups | result_options::path | result_options::sort_descending;
        expr.evaluate(context, root, path_node_type{}, root, f, options);
    }

} // namespace jsonpath
} // namespace jsoncons

#endif // JSONCONS_EXT_JSONPATH_JSON_QUERY_HPP