1//
2// Query.cpp
3//
4// Library: JSON
5// Package: JSON
6// Module: Query
7//
8// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/JSON/Query.h"
16#include "Poco/StringTokenizer.h"
17#include "Poco/RegularExpression.h"
18#include "Poco/NumberParser.h"
19#include <sstream>
20
21
22using Poco::Dynamic::Var;
23
24
25namespace Poco {
26namespace JSON {
27
28
29Query::Query(const Var& source): _source(source)
30{
31 if (!source.isEmpty() &&
32 source.type() != typeid(Object) &&
33 source.type() != typeid(Object::Ptr) &&
34 source.type() != typeid(Array) &&
35 source.type() != typeid(Array::Ptr))
36 throw InvalidArgumentException("Only JSON Object, Array or pointers thereof allowed.");
37}
38
39
40Query::~Query()
41{
42}
43
44
45Object::Ptr Query::findObject(const std::string& path) const
46{
47 Var result = find(path);
48
49 if (result.type() == typeid(Object::Ptr))
50 return result.extract<Object::Ptr>();
51 else if (result.type() == typeid(Object))
52 return new Object(result.extract<Object>());
53
54 return 0;
55}
56
57
58Object& Query::findObject(const std::string& path, Object& obj) const
59{
60 obj.clear();
61
62 Var result = find(path);
63
64 if (result.type() == typeid(Object::Ptr))
65 obj = *result.extract<Object::Ptr>();
66 else if (result.type() == typeid(Object))
67 obj = result.extract<Object>();
68
69 return obj;
70}
71
72
73Array::Ptr Query::findArray(const std::string& path) const
74{
75 Var result = find(path);
76
77 if (result.type() == typeid(Array::Ptr))
78 return result.extract<Array::Ptr>();
79 else if (result.type() == typeid(Array))
80 return new Array(result.extract<Array>());
81
82 return 0;
83}
84
85
86Array& Query::findArray(const std::string& path, Array& arr) const
87{
88 arr.clear();
89
90 Var result = find(path);
91
92 if (result.type() == typeid(Array::Ptr))
93 arr = *result.extract<Array::Ptr>();
94 else if (result.type() == typeid(Array))
95 arr = result.extract<Array>();
96
97 return arr;
98}
99
100
101Var Query::find(const std::string& path) const
102{
103 Var result = _source;
104 StringTokenizer tokenizer(path, ".");
105 for (StringTokenizer::Iterator token = tokenizer.begin(); token != tokenizer.end(); token++)
106 {
107 if (!result.isEmpty())
108 {
109 std::vector<int> indexes;
110 RegularExpression::MatchVec matches;
111 int firstOffset = -1;
112 int offset = 0;
113 RegularExpression regex("\\[([0-9]+)\\]");
114 while (regex.match(*token, offset, matches) > 0)
115 {
116 if (firstOffset == -1)
117 {
118 firstOffset = static_cast<int>(matches[0].offset);
119 }
120 std::string num = token->substr(matches[1].offset, matches[1].length);
121 indexes.push_back(NumberParser::parse(num));
122 offset = static_cast<int>(matches[0].offset + matches[0].length);
123 }
124
125 std::string name(*token);
126 if (firstOffset != -1)
127 {
128 name = name.substr(0, firstOffset);
129 }
130
131 if (name.length() > 0)
132 {
133 if (result.type() == typeid(Object::Ptr))
134 {
135 Object::Ptr o = result.extract<Object::Ptr>();
136 result = o->get(name);
137 }
138 else if (result.type() == typeid(Object))
139 {
140 Object o = result.extract<Object>();
141 result = o.get(name);
142 }
143 else
144 result.empty();
145
146 }
147
148 if (!result.isEmpty() && !indexes.empty())
149 {
150 for (std::vector<int>::iterator it = indexes.begin(); it != indexes.end(); ++it)
151 {
152 if (result.type() == typeid(Array::Ptr))
153 {
154 Array::Ptr array = result.extract<Array::Ptr>();
155 result = array->get(*it);
156 if (result.isEmpty()) break;
157 }
158 else if (result.type() == typeid(Array))
159 {
160 Array array = result.extract<Array>();
161 result = array.get(*it);
162 if (result.isEmpty()) break;
163 }
164 }
165 }
166 }
167 }
168 return result;
169}
170
171
172} } // namespace Poco::JSON
173