1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "json_object.h"
17
18 #include <algorithm>
19 #include <cmath>
20 #include <queue>
21
22 #include "db_errno.h"
23 #include "log_print.h"
24
25 namespace DistributedDB {
26 #ifndef OMIT_JSON
27 namespace {
28 const uint32_t MAX_NEST_DEPTH = 100;
29 #ifdef JSONCPP_USE_BUILDER
30 const int JSON_VALUE_PRECISION = 16;
31 const std::string JSON_CONFIG_INDENTATION = "indentation";
32 const std::string JSON_CONFIG_COLLECT_COMMENTS = "collectComments";
33 const std::string JSON_CONFIG_PRECISION = "precision";
34 const std::string JSON_CONFIG_REJECT_DUP_KEYS = "rejectDupKeys";
35 #endif
36 }
37 uint32_t JsonObject::maxNestDepth_ = MAX_NEST_DEPTH;
38
SetMaxNestDepth(uint32_t nestDepth)39 uint32_t JsonObject::SetMaxNestDepth(uint32_t nestDepth)
40 {
41 uint32_t preValue = maxNestDepth_;
42 // No need to check the reasonability, only test code will use this method
43 maxNestDepth_ = nestDepth;
44 return preValue;
45 }
46
CalculateNestDepth(const std::string & inString,int & errCode)47 uint32_t JsonObject::CalculateNestDepth(const std::string &inString, int &errCode)
48 {
49 auto begin = reinterpret_cast<const uint8_t *>(inString.c_str());
50 auto end = begin + inString.size();
51 return CalculateNestDepth(begin, end, errCode);
52 }
53
CalculateNestDepth(const uint8_t * dataBegin,const uint8_t * dataEnd,int & errCode)54 uint32_t JsonObject::CalculateNestDepth(const uint8_t *dataBegin, const uint8_t *dataEnd, int &errCode)
55 {
56 if (dataBegin == nullptr || dataEnd == nullptr || dataBegin >= dataEnd) {
57 errCode = -E_INVALID_ARGS;
58 return maxNestDepth_ + 1; // return a invalid depth
59 }
60 bool isInString = false;
61 uint32_t maxDepth = 0;
62 uint32_t objectDepth = 0;
63 uint32_t arrayDepth = 0;
64 uint32_t numOfEscape = 0;
65
66 for (auto ptr = dataBegin; ptr < dataEnd; ptr++) {
67 if (*ptr == '"' && numOfEscape % 2 == 0) { // 2 used to detect parity
68 isInString = !isInString;
69 continue;
70 }
71 if (!isInString) {
72 if (*ptr == '{') {
73 objectDepth++;
74 maxDepth = std::max(maxDepth, objectDepth + arrayDepth);
75 }
76 if (*ptr == '}') {
77 objectDepth = ((objectDepth > 0) ? (objectDepth - 1) : 0);
78 }
79 if (*ptr == '[') {
80 arrayDepth++;
81 maxDepth = std::max(maxDepth, objectDepth + arrayDepth);
82 }
83 if (*ptr == ']') {
84 arrayDepth = ((arrayDepth > 0) ? (arrayDepth - 1) : 0);
85 }
86 }
87 numOfEscape = ((*ptr == '\\') ? (numOfEscape + 1) : 0);
88 }
89 return maxDepth;
90 }
91
JsonObject(const JsonObject & other)92 JsonObject::JsonObject(const JsonObject &other)
93 {
94 isValid_ = other.isValid_;
95 value_ = other.value_;
96 }
97
operator =(const JsonObject & other)98 JsonObject& JsonObject::operator=(const JsonObject &other)
99 {
100 if (&other != this) {
101 isValid_ = other.isValid_;
102 value_ = other.value_;
103 }
104 return *this;
105 }
106
JsonObject(const Json::Value & value)107 JsonObject::JsonObject(const Json::Value &value) : isValid_(true), value_(value)
108 {
109 }
110
Parse(const std::string & inString)111 int JsonObject::Parse(const std::string &inString)
112 {
113 // The jsoncpp lib parser in strict mode will still regard root type jsonarray as valid, but we require jsonobject
114 if (isValid_) {
115 LOGE("[Json][Parse] Already Valid.");
116 return -E_NOT_PERMIT;
117 }
118 int errCode = E_OK;
119 uint32_t nestDepth = CalculateNestDepth(inString, errCode);
120 if (errCode != E_OK || nestDepth > maxNestDepth_) {
121 LOGE("[Json][Parse] Json calculate nest depth failed %d, depth=%" PRIu32 " exceed max allowed:%" PRIu32,
122 errCode, nestDepth, maxNestDepth_);
123 return -E_JSON_PARSE_FAIL;
124 }
125 #ifdef JSONCPP_USE_BUILDER
126 JSONCPP_STRING errs;
127 Json::CharReaderBuilder builder;
128 Json::CharReaderBuilder::strictMode(&builder.settings_);
129 builder[JSON_CONFIG_COLLECT_COMMENTS] = false;
130 builder[JSON_CONFIG_REJECT_DUP_KEYS] = false;
131 std::unique_ptr<Json::CharReader> const jsonReader(builder.newCharReader());
132
133 auto begin = reinterpret_cast<const std::string::value_type *>(inString.c_str());
134 auto end = reinterpret_cast<const std::string::value_type *>(inString.c_str() + inString.length());
135 if (!jsonReader->parse(begin, end, &value_, &errs)) {
136 value_ = Json::Value();
137 LOGE("[Json][Parse] Parse string to JsonValue fail, reason=%s.", errs.c_str());
138 return -E_JSON_PARSE_FAIL;
139 }
140 #else
141 Json::Reader reader(Json::Features::strictMode());
142 if (!reader.parse(inString, value_, false)) {
143 value_ = Json::Value();
144 LOGE("[Json][Parse] Parse string to JsonValue fail, reason=%s.", reader.getFormattedErrorMessages().c_str());
145 return -E_JSON_PARSE_FAIL;
146 }
147 #endif
148 // The jsoncpp lib parser in strict mode will still regard root type jsonarray as valid, but we require jsonobject
149 if (value_.type() != Json::ValueType::objectValue) {
150 value_ = Json::Value();
151 LOGE("[Json][Parse] Not an object at root.");
152 return -E_JSON_PARSE_FAIL;
153 }
154 isValid_ = true;
155 return E_OK;
156 }
157
Parse(const std::vector<uint8_t> & inData)158 int JsonObject::Parse(const std::vector<uint8_t> &inData)
159 {
160 if (inData.empty()) {
161 return -E_INVALID_ARGS;
162 }
163 return Parse(inData.data(), inData.data() + inData.size());
164 }
165
Parse(const uint8_t * dataBegin,const uint8_t * dataEnd)166 int JsonObject::Parse(const uint8_t *dataBegin, const uint8_t *dataEnd)
167 {
168 if (isValid_) {
169 LOGE("[Json][Parse] Already Valid.");
170 return -E_NOT_PERMIT;
171 }
172 if (dataBegin == nullptr || dataEnd == nullptr || dataBegin >= dataEnd) {
173 return -E_INVALID_ARGS;
174 }
175 int errCode = E_OK;
176 uint32_t nestDepth = CalculateNestDepth(dataBegin, dataEnd, errCode);
177 if (errCode != E_OK || nestDepth > maxNestDepth_) {
178 LOGE("[Json][Parse] Json calculate nest depth failed %d, depth:%" PRIu32 " exceed max allowed:%" PRIu32,
179 errCode, nestDepth, maxNestDepth_);
180 return -E_JSON_PARSE_FAIL;
181 }
182 #ifdef JSONCPP_USE_BUILDER
183 auto begin = reinterpret_cast<const std::string::value_type *>(dataBegin);
184 auto end = reinterpret_cast<const std::string::value_type *>(dataEnd);
185
186 JSONCPP_STRING errs;
187 Json::CharReaderBuilder builder;
188 Json::CharReaderBuilder::strictMode(&builder.settings_);
189 builder[JSON_CONFIG_COLLECT_COMMENTS] = false;
190 builder[JSON_CONFIG_REJECT_DUP_KEYS] = false;
191 std::unique_ptr<Json::CharReader> const jsonReader(builder.newCharReader());
192 // The endDoc parameter of reader::parse refer to the byte after the string itself
193 if (!jsonReader->parse(begin, end, &value_, &errs)) {
194 value_ = Json::Value();
195 LOGE("[Json][Parse] Parse dataRange to JsonValue fail, reason=%s.", errs.c_str());
196 return -E_JSON_PARSE_FAIL;
197 }
198 #else
199 Json::Reader reader(Json::Features::strictMode());
200 auto begin = reinterpret_cast<const std::string::value_type *>(dataBegin);
201 auto end = reinterpret_cast<const std::string::value_type *>(dataEnd);
202 // The endDoc parameter of reader::parse refer to the byte after the string itself
203 if (!reader.parse(begin, end, value_, false)) {
204 value_ = Json::Value();
205 LOGE("[Json][Parse] Parse dataRange to JsonValue fail, reason=%s.", reader.getFormattedErrorMessages().c_str());
206 return -E_JSON_PARSE_FAIL;
207 }
208 #endif
209 // The jsoncpp lib parser in strict mode will still regard root type jsonarray as valid, but we require jsonobject
210 if (value_.type() != Json::ValueType::objectValue) {
211 value_ = Json::Value();
212 LOGE("[Json][Parse] Not an object at root.");
213 return -E_JSON_PARSE_FAIL;
214 }
215 isValid_ = true;
216 return E_OK;
217 }
218
IsValid() const219 bool JsonObject::IsValid() const
220 {
221 return isValid_;
222 }
223
ToString() const224 std::string JsonObject::ToString() const
225 {
226 if (!isValid_) {
227 LOGE("[Json][ToString] Not Valid Yet.");
228 return std::string();
229 }
230 #ifdef JSONCPP_USE_BUILDER
231 Json::StreamWriterBuilder writerBuilder;
232 writerBuilder[JSON_CONFIG_INDENTATION] = "";
233 writerBuilder[JSON_CONFIG_PRECISION] = JSON_VALUE_PRECISION;
234 std::unique_ptr<Json::StreamWriter> const jsonWriter(writerBuilder.newStreamWriter());
235 std::stringstream ss;
236 jsonWriter->write(value_, &ss);
237 // The endingLineFeedSymbol is left empty by default.
238 return ss.str();
239 #else
240 Json::FastWriter fastWriter;
241 // Call omitEndingLineFeed to let JsonCpp not append an \n at the end of string. If not doing so, when passing a
242 // minified jsonString, the result of this function will be one byte longer then the original, which may cause the
243 // result checked as length invalid by upper logic when the original length is just at the limitation boundary.
244 fastWriter.omitEndingLineFeed();
245 return fastWriter.write(value_);
246 #endif
247 }
248
IsFieldPathExist(const FieldPath & inPath) const249 bool JsonObject::IsFieldPathExist(const FieldPath &inPath) const
250 {
251 if (!isValid_) {
252 LOGE("[Json][isExisted] Not Valid Yet.");
253 return false;
254 }
255 int errCode = E_OK;
256 (void)GetJsonValueByFieldPath(inPath, errCode); // Ignore return const reference
257 return (errCode == E_OK);
258 }
259
GetFieldTypeByFieldPath(const FieldPath & inPath,FieldType & outType) const260 int JsonObject::GetFieldTypeByFieldPath(const FieldPath &inPath, FieldType &outType) const
261 {
262 if (!isValid_) {
263 LOGE("[Json][GetType] Not Valid Yet.");
264 return -E_NOT_PERMIT;
265 }
266 int errCode = E_OK;
267 const Json::Value &valueNode = GetJsonValueByFieldPath(inPath, errCode);
268 if (errCode != E_OK) {
269 return errCode;
270 }
271 return GetFieldTypeByJsonValue(valueNode, outType);
272 }
273
GetFieldValueByFieldPath(const FieldPath & inPath,FieldValue & outValue) const274 int JsonObject::GetFieldValueByFieldPath(const FieldPath &inPath, FieldValue &outValue) const
275 {
276 if (!isValid_) {
277 LOGE("[Json][GetValue] Not Valid Yet.");
278 return -E_NOT_PERMIT;
279 }
280 int errCode = E_OK;
281 const Json::Value &valueNode = GetJsonValueByFieldPath(inPath, errCode);
282 if (errCode != E_OK) {
283 return errCode;
284 }
285 FieldType valueType;
286 errCode = GetFieldTypeByJsonValue(valueNode, valueType);
287 if (errCode != E_OK) {
288 return errCode;
289 }
290 switch (valueType) {
291 case FieldType::LEAF_FIELD_BOOL:
292 outValue.boolValue = valueNode.asBool();
293 break;
294 case FieldType::LEAF_FIELD_INTEGER:
295 outValue.integerValue = valueNode.asInt();
296 break;
297 case FieldType::LEAF_FIELD_LONG:
298 outValue.longValue = valueNode.asInt64();
299 break;
300 case FieldType::LEAF_FIELD_DOUBLE:
301 outValue.doubleValue = valueNode.asDouble();
302 break;
303 case FieldType::LEAF_FIELD_STRING:
304 outValue.stringValue = valueNode.asString();
305 break;
306 default:
307 return -E_NOT_SUPPORT;
308 }
309 return E_OK;
310 }
311
GetSubFieldPath(const FieldPath & inPath,std::set<FieldPath> & outSubPath) const312 int JsonObject::GetSubFieldPath(const FieldPath &inPath, std::set<FieldPath> &outSubPath) const
313 {
314 if (!isValid_) {
315 LOGE("[Json][GetSubPath] Not Valid Yet.");
316 return -E_NOT_PERMIT;
317 }
318 int errCode = E_OK;
319 const Json::Value &valueNode = GetJsonValueByFieldPath(inPath, errCode);
320 if (errCode != E_OK) {
321 return errCode;
322 }
323 if (valueNode.type() != Json::ValueType::objectValue) {
324 return -E_NOT_SUPPORT;
325 }
326 // Note: the subFields JsonCpp returnout will be different from each other
327 std::vector<std::string> subFields = valueNode.getMemberNames();
328 for (const auto &eachSubField : subFields) {
329 FieldPath eachSubPath = inPath;
330 eachSubPath.push_back(eachSubField);
331 outSubPath.insert(eachSubPath);
332 }
333 return E_OK;
334 }
335
GetSubFieldPath(const std::set<FieldPath> & inPath,std::set<FieldPath> & outSubPath) const336 int JsonObject::GetSubFieldPath(const std::set<FieldPath> &inPath, std::set<FieldPath> &outSubPath) const
337 {
338 for (const auto &eachPath : inPath) {
339 int errCode = GetSubFieldPath(eachPath, outSubPath);
340 if (errCode != E_OK) {
341 return errCode;
342 }
343 }
344 return E_OK;
345 }
346
GetSubFieldPathAndType(const FieldPath & inPath,std::map<FieldPath,FieldType> & outSubPathType) const347 int JsonObject::GetSubFieldPathAndType(const FieldPath &inPath, std::map<FieldPath, FieldType> &outSubPathType) const
348 {
349 if (!isValid_) {
350 LOGE("[Json][GetSubPathType] Not Valid Yet.");
351 return -E_NOT_PERMIT;
352 }
353 int errCode = E_OK;
354 const Json::Value &valueNode = GetJsonValueByFieldPath(inPath, errCode);
355 if (errCode != E_OK) {
356 return errCode;
357 }
358 if (valueNode.type() != Json::ValueType::objectValue) {
359 return -E_NOT_SUPPORT;
360 }
361 // Note: the subFields JsonCpp returnout will be different from each other
362 std::vector<std::string> subFields = valueNode.getMemberNames();
363 for (const auto &eachSubField : subFields) {
364 FieldPath eachSubPath = inPath;
365 eachSubPath.push_back(eachSubField);
366 FieldType eachSubType;
367 errCode = GetFieldTypeByJsonValue(valueNode[eachSubField], eachSubType);
368 if (errCode != E_OK) {
369 return errCode;
370 }
371 outSubPathType[eachSubPath] = eachSubType;
372 }
373 return E_OK;
374 }
375
GetSubFieldPathAndType(const std::set<FieldPath> & inPath,std::map<FieldPath,FieldType> & outSubPathType) const376 int JsonObject::GetSubFieldPathAndType(const std::set<FieldPath> &inPath,
377 std::map<FieldPath, FieldType> &outSubPathType) const
378 {
379 for (const auto &eachPath : inPath) {
380 int errCode = GetSubFieldPathAndType(eachPath, outSubPathType);
381 if (errCode != E_OK) {
382 return errCode;
383 }
384 }
385 return E_OK;
386 }
387
GetArraySize(const FieldPath & inPath,uint32_t & outSize) const388 int JsonObject::GetArraySize(const FieldPath &inPath, uint32_t &outSize) const
389 {
390 if (!isValid_) {
391 LOGE("[Json][GetArraySize] Not Valid Yet.");
392 return -E_NOT_PERMIT;
393 }
394 int errCode = E_OK;
395 const Json::Value &valueNode = GetJsonValueByFieldPath(inPath, errCode);
396 if (errCode != E_OK) {
397 return errCode;
398 }
399 if (valueNode.type() != Json::ValueType::arrayValue) {
400 return -E_NOT_SUPPORT;
401 }
402 outSize = valueNode.size();
403 return E_OK;
404 }
405
GetArrayContentOfStringOrStringArray(const FieldPath & inPath,std::vector<std::vector<std::string>> & outContent) const406 int JsonObject::GetArrayContentOfStringOrStringArray(const FieldPath &inPath,
407 std::vector<std::vector<std::string>> &outContent) const
408 {
409 if (!isValid_) {
410 LOGE("[Json][GetArrayContent] Not Valid Yet.");
411 return -E_NOT_PERMIT;
412 }
413 int errCode = E_OK;
414 const Json::Value &valueNode = GetJsonValueByFieldPath(inPath, errCode);
415 if (errCode != E_OK) {
416 LOGW("[Json][GetArrayContent] Get JsonValue Fail=%d.", errCode);
417 return errCode;
418 }
419 if (valueNode.type() != Json::ValueType::arrayValue) {
420 LOGE("[Json][GetArrayContent] Not an array.");
421 return -E_NOT_SUPPORT;
422 }
423 for (uint32_t index = 0; index < valueNode.size(); index++) {
424 const Json::Value &eachArrayItem = valueNode[index];
425 if (eachArrayItem.isString()) {
426 outContent.emplace_back(std::vector<std::string>({eachArrayItem.asString()}));
427 continue;
428 }
429 if (eachArrayItem.isArray()) {
430 if (eachArrayItem.empty()) {
431 continue; // Ignore empty array-type member
432 }
433 outContent.emplace_back(std::vector<std::string>());
434 errCode = GetStringArrayContentByJsonValue(eachArrayItem, outContent.back());
435 if (errCode == E_OK) {
436 continue; // Everything ok
437 }
438 }
439 // If reach here, then something is not ok
440 outContent.clear();
441 LOGE("[Json][GetArrayContent] Not string or array fail=%d at index:%" PRIu32, errCode, index);
442 return -E_NOT_SUPPORT;
443 }
444 return E_OK;
445 }
446
447 namespace {
InsertFieldCheckParameter(const FieldPath & inPath,FieldType inType,const FieldValue & inValue,uint32_t maxNestDepth)448 bool InsertFieldCheckParameter(const FieldPath &inPath, FieldType inType, const FieldValue &inValue,
449 uint32_t maxNestDepth)
450 {
451 if (inPath.empty() || inPath.size() > maxNestDepth || inType == FieldType::LEAF_FIELD_ARRAY ||
452 inType == FieldType::INTERNAL_FIELD_OBJECT) {
453 return false;
454 }
455 // Infinite double not support
456 return !(inType == FieldType::LEAF_FIELD_DOUBLE && !std::isfinite(inValue.doubleValue));
457 }
458
LeafJsonNodeAppendValue(Json::Value & leafNode,FieldType inType,const FieldValue & inValue)459 void LeafJsonNodeAppendValue(Json::Value &leafNode, FieldType inType, const FieldValue &inValue)
460 {
461 if (inType == FieldType::LEAF_FIELD_STRING) {
462 leafNode.append(Json::Value(inValue.stringValue));
463 }
464 }
465
466 // Function design for InsertField call on an null-type Json::Value
LeafJsonNodeAssignValue(Json::Value & leafNode,FieldType inType,const FieldValue & inValue)467 void LeafJsonNodeAssignValue(Json::Value &leafNode, FieldType inType, const FieldValue &inValue)
468 {
469 switch (inType) {
470 case FieldType::LEAF_FIELD_BOOL:
471 leafNode = Json::Value(inValue.boolValue);
472 break;
473 case FieldType::LEAF_FIELD_INTEGER:
474 // Cast to Json::Int to avoid "ambiguous call of overloaded function"
475 leafNode = Json::Value(static_cast<Json::Int>(inValue.integerValue));
476 break;
477 case FieldType::LEAF_FIELD_LONG:
478 // Cast to Json::Int64 to avoid "ambiguous call of overloaded function"
479 leafNode = Json::Value(static_cast<Json::Int64>(inValue.longValue));
480 break;
481 case FieldType::LEAF_FIELD_DOUBLE:
482 leafNode = Json::Value(inValue.doubleValue);
483 break;
484 case FieldType::LEAF_FIELD_STRING:
485 leafNode = Json::Value(inValue.stringValue);
486 break;
487 case FieldType::LEAF_FIELD_OBJECT:
488 leafNode = Json::Value(Json::ValueType::objectValue);
489 break;
490 default:
491 // For LEAF_FIELD_NULL, Do nothing.
492 // For LEAF_FIELD_ARRAY and INTERNAL_FIELD_OBJECT, Not Support, had been excluded by InsertField
493 return;
494 }
495 }
496 }
497
498 // move the nearest to the leaf of inPath, if not exist, will create it, else it should be an array object.
MoveToPath(const FieldPath & inPath,Json::Value * & exact,Json::Value * & nearest)499 int JsonObject::MoveToPath(const FieldPath &inPath, Json::Value *&exact, Json::Value *&nearest)
500 {
501 uint32_t nearDepth = 0;
502 int errCode = LocateJsonValueByFieldPath(inPath, exact, nearest, nearDepth);
503 if (errCode != -E_NOT_FOUND) { // Path already exist and it's not an array object
504 return -E_JSON_INSERT_PATH_EXIST;
505 }
506 // nearDepth 0 represent for root value. nearDepth equal to inPath.size indicate an exact path match
507 if (nearest == nullptr || nearDepth >= inPath.size()) { // Impossible
508 return -E_INTERNAL_ERROR;
509 }
510 if (nearest->type() != Json::ValueType::objectValue) { // path ends with type not object
511 return -E_JSON_INSERT_PATH_CONFLICT;
512 }
513 // Use nearDepth as startIndex pointing to the first field that lacked
514 for (uint32_t lackFieldIndex = nearDepth; lackFieldIndex < inPath.size(); lackFieldIndex++) {
515 // The new JsonValue is null-type, we can safely add members to an null-type JsonValue which will turn into
516 // object-type after member adding. Then move "nearest" to point to the new JsonValue.
517 nearest = &((*nearest)[inPath[lackFieldIndex]]);
518 }
519 return E_OK;
520 }
521
InsertField(const FieldPath & inPath,const JsonObject & inValue,bool isAppend)522 int JsonObject::InsertField(const FieldPath &inPath, const JsonObject &inValue, bool isAppend)
523 {
524 if (inPath.empty() || inPath.size() > maxNestDepth_ || !inValue.IsValid()) {
525 return -E_INVALID_ARGS;
526 }
527 if (!isValid_) {
528 value_ = Json::Value(Json::ValueType::objectValue);
529 isValid_ = true;
530 }
531 Json::Value *exact = nullptr;
532 Json::Value *nearest = nullptr;
533 int errCode = MoveToPath(inPath, exact, nearest);
534 if (errCode != E_OK) {
535 return errCode;
536 }
537 LOGD("nearest type is %d", nearest->type());
538 if (isAppend || nearest->type() == Json::ValueType::arrayValue) {
539 nearest->append(inValue.value_);
540 } else {
541 *nearest = inValue.value_;
542 }
543 return E_OK;
544 }
545
InsertField(const FieldPath & inPath,FieldType inType,const FieldValue & inValue,bool isAppend)546 int JsonObject::InsertField(const FieldPath &inPath, FieldType inType, const FieldValue &inValue, bool isAppend)
547 {
548 if (!InsertFieldCheckParameter(inPath, inType, inValue, maxNestDepth_)) {
549 return -E_INVALID_ARGS;
550 }
551 if (!isValid_) {
552 // Insert on invalid object never fail after parameter check ok, so here no need concern rollback.
553 value_ = Json::Value(Json::ValueType::objectValue);
554 isValid_ = true;
555 }
556 Json::Value *exact = nullptr;
557 Json::Value *nearest = nullptr;
558 int errCode = MoveToPath(inPath, exact, nearest);
559 if (errCode != E_OK) {
560 return errCode;
561 }
562 // Here "nearest" points to the JsonValue(null-type now) corresponding to the last field
563 if (isAppend || nearest->type() == Json::ValueType::arrayValue) {
564 LeafJsonNodeAppendValue(*nearest, inType, inValue);
565 } else {
566 LeafJsonNodeAssignValue(*nearest, inType, inValue);
567 }
568 return E_OK;
569 }
570
DeleteField(const FieldPath & inPath)571 int JsonObject::DeleteField(const FieldPath &inPath)
572 {
573 if (!isValid_) {
574 LOGE("[Json][DeleteField] Not Valid Yet.");
575 return -E_NOT_PERMIT;
576 }
577 if (inPath.empty()) {
578 return -E_INVALID_ARGS;
579 }
580 Json::Value *exact = nullptr;
581 Json::Value *nearest = nullptr;
582 uint32_t nearDepth = 0;
583 int errCode = LocateJsonValueByFieldPath(inPath, exact, nearest, nearDepth);
584 if (errCode != E_OK) { // Path not exist
585 return -E_JSON_DELETE_PATH_NOT_FOUND;
586 }
587 // nearDepth should be equal to inPath.size() - 1, because nearest is at the parent path of inPath
588 if (nearest == nullptr || nearest->type() != Json::ValueType::objectValue || nearDepth != inPath.size() - 1) {
589 return -E_INTERNAL_ERROR; // Impossible
590 }
591 // Remove member from nearest, ignore returned removed Value, use nearDepth as index pointing to last field of path.
592 (void)nearest->removeMember(inPath[nearDepth]);
593 return E_OK;
594 }
595
GetStringArrayContentByJsonValue(const Json::Value & value,std::vector<std::string> & outStringArray) const596 int JsonObject::GetStringArrayContentByJsonValue(const Json::Value &value,
597 std::vector<std::string> &outStringArray) const
598 {
599 if (value.type() != Json::ValueType::arrayValue) {
600 LOGE("[Json][GetStringArrayByValue] Not an array.");
601 return -E_NOT_SUPPORT;
602 }
603 for (uint32_t index = 0; index < value.size(); index++) {
604 const Json::Value &eachArrayItem = value[index];
605 if (!eachArrayItem.isString()) {
606 LOGE("[Json][GetStringArrayByValue] Index=%u in Array is not string.", index);
607 outStringArray.clear();
608 return -E_NOT_SUPPORT;
609 }
610 outStringArray.push_back(eachArrayItem.asString());
611 }
612 return E_OK;
613 }
614
GetFieldTypeByJsonValue(const Json::Value & value,FieldType & outType) const615 int JsonObject::GetFieldTypeByJsonValue(const Json::Value &value, FieldType &outType) const
616 {
617 Json::ValueType valueType = value.type();
618 switch (valueType) {
619 case Json::ValueType::nullValue:
620 outType = FieldType::LEAF_FIELD_NULL;
621 break;
622 case Json::ValueType::booleanValue:
623 outType = FieldType::LEAF_FIELD_BOOL;
624 break;
625 // The case intValue and uintValue cover from INT64_MIN to UINT64_MAX. Inside this range, isInt() take range
626 // from INT32_MIN to INT32_MAX, which should be regard as LEAF_FIELD_INTEGER; isInt64() take range from
627 // INT64_MIN to INT64_MAX, which should be regard as LEAF_FIELD_LONG if it is not LEAF_FIELD_INTEGER;
628 // INT64_MAX + 1 to UINT64_MAX will be regard as LEAF_FIELD_DOUBLE, therefore lose its precision when read out
629 // as double value.
630 case Json::ValueType::intValue:
631 case Json::ValueType::uintValue:
632 if (value.isInt()) {
633 outType = FieldType::LEAF_FIELD_INTEGER;
634 } else if (value.isInt64()) {
635 outType = FieldType::LEAF_FIELD_LONG;
636 } else {
637 outType = FieldType::LEAF_FIELD_DOUBLE; // The isDouble() judge is always true in this case.
638 }
639 break;
640 // Integral value beyond range INT64_MIN to UINT64_MAX will be recognized as realValue and lose its precision.
641 // Value in scientific notation or has decimal point will be recognized as realValue without exception,
642 // no matter whether the value is large or small, no matter with or without non-zero decimal part.
643 // In a word, when regard as DOUBLE type, a value can not guarantee its presision
644 case Json::ValueType::realValue:
645 // The isDouble() judge is always true in this case. A value exceed double range is not support.
646 outType = FieldType::LEAF_FIELD_DOUBLE;
647 if (!std::isfinite(value.asDouble())) {
648 LOGE("[Json][GetTypeByJson] Infinite double not support.");
649 return -E_NOT_SUPPORT;
650 }
651 break;
652 case Json::ValueType::stringValue:
653 outType = FieldType::LEAF_FIELD_STRING;
654 break;
655 case Json::ValueType::arrayValue:
656 outType = FieldType::LEAF_FIELD_ARRAY;
657 break;
658 case Json::ValueType::objectValue:
659 if (value.getMemberNames().empty()) {
660 outType = FieldType::LEAF_FIELD_OBJECT;
661 break;
662 }
663 outType = FieldType::INTERNAL_FIELD_OBJECT;
664 break;
665 default:
666 LOGE("[Json][GetTypeByJson] no such type.");
667 return -E_NOT_SUPPORT;
668 }
669 return E_OK;
670 }
671
GetJsonValueByFieldPath(const FieldPath & inPath,int & errCode) const672 const Json::Value &JsonObject::GetJsonValueByFieldPath(const FieldPath &inPath, int &errCode) const
673 {
674 // Root path always exist
675 if (inPath.empty()) {
676 errCode = E_OK;
677 return value_;
678 }
679 const Json::Value *valueNode = &value_;
680 for (const auto &eachPathSegment : inPath) {
681 if ((valueNode->type() != Json::ValueType::objectValue) || (!valueNode->isMember(eachPathSegment))) {
682 // Current JsonValue is not an object, or no such member field
683 errCode = -E_INVALID_PATH;
684 return value_;
685 }
686 valueNode = &((*valueNode)[eachPathSegment]);
687 }
688 errCode = E_OK;
689 return *valueNode;
690 }
691
LocateJsonValueByFieldPath(const FieldPath & inPath,Json::Value * & exact,Json::Value * & nearest,uint32_t & nearDepth)692 int JsonObject::LocateJsonValueByFieldPath(const FieldPath &inPath, Json::Value *&exact,
693 Json::Value *&nearest, uint32_t &nearDepth)
694 {
695 if (!isValid_) {
696 return -E_NOT_PERMIT;
697 }
698 exact = &value_;
699 nearest = &value_;
700 nearDepth = 0;
701 if (inPath.empty()) {
702 return E_OK;
703 }
704 for (const auto &eachPathSegment : inPath) {
705 nearest = exact; // Let "nearest" trace "exact" before "exact" go deeper
706 if (nearest != &value_) {
707 nearDepth++; // For each "nearest" trace up "exact", increase nearDepth to indicate where it is.
708 }
709 if ((exact->type() != Json::ValueType::objectValue) || (!exact->isMember(eachPathSegment))) {
710 // "exact" is not an object, or no such member field
711 exact = nullptr; // Set "exact" to nullptr indicate exact path not exist
712 return -E_NOT_FOUND;
713 }
714 exact = &((*exact)[eachPathSegment]); // "exact" go deeper
715 }
716 if (exact->type() == Json::ValueType::arrayValue) {
717 return -E_NOT_FOUND; // could append value if path is an array field.
718 }
719 // Here, JsonValue exist at exact path, "nearest" is "exact" parent.
720 return E_OK;
721 }
722
GetObjectArrayByFieldPath(const FieldPath & inPath,std::vector<JsonObject> & outArray) const723 int JsonObject::GetObjectArrayByFieldPath(const FieldPath &inPath, std::vector<JsonObject> &outArray) const
724 {
725 if (!isValid_) {
726 LOGE("[Json][GetValue] Not Valid Yet.");
727 return -E_NOT_PERMIT;
728 }
729 int errCode = E_OK;
730 const Json::Value &valueNode = GetJsonValueByFieldPath(inPath, errCode);
731 if (errCode != E_OK) {
732 LOGE("[Json][GetValue] Get json value failed. %d", errCode);
733 return errCode;
734 }
735
736 if (!valueNode.isArray()) {
737 LOGE("[Json][GetValue] Not Array type.");
738 return -E_NOT_PERMIT;
739 }
740 for (Json::ArrayIndex i = 0; i < valueNode.size(); ++i) {
741 outArray.emplace_back(JsonObject(valueNode[i]));
742 }
743 return E_OK;
744 }
745
GetObjectByFieldPath(const FieldPath & inPath,JsonObject & outObj) const746 int JsonObject::GetObjectByFieldPath(const FieldPath &inPath, JsonObject &outObj) const
747 {
748 if (!isValid_) {
749 LOGE("[Json][GetValue] Not Valid Yet.");
750 return -E_NOT_PERMIT;
751 }
752 int errCode = E_OK;
753 const Json::Value &valueNode = GetJsonValueByFieldPath(inPath, errCode);
754 if (errCode != E_OK) {
755 LOGE("[Json][GetValue] Get json value failed. %d", errCode);
756 return errCode;
757 }
758
759 if (!valueNode.isObject()) {
760 LOGE("[Json][GetValue] Not Object type.");
761 return -E_NOT_PERMIT;
762 }
763 outObj = JsonObject(valueNode);
764 return E_OK;
765 }
766
GetStringArrayByFieldPath(const FieldPath & inPath,std::vector<std::string> & outArray) const767 int JsonObject::GetStringArrayByFieldPath(const FieldPath &inPath, std::vector<std::string> &outArray) const
768 {
769 if (!isValid_) {
770 LOGE("[Json][GetValue] Not Valid Yet.");
771 return -E_NOT_PERMIT;
772 }
773 int errCode = E_OK;
774 const Json::Value &valueNode = GetJsonValueByFieldPath(inPath, errCode);
775 if (errCode != E_OK) {
776 LOGE("[Json][GetValue] Get json value failed. %d", errCode);
777 return errCode;
778 }
779
780 return GetStringArrayContentByJsonValue(valueNode, outArray);
781 }
782
783 #else // OMIT_JSON
784 uint32_t JsonObject::SetMaxNestDepth(uint32_t nestDepth)
785 {
786 (void)nestDepth;
787 return 0;
788 }
789
790 uint32_t JsonObject::CalculateNestDepth(const std::string &inString, int &errCode)
791 {
792 (void)inString;
793 (void)errCode;
794 return 0;
795 }
796
797 uint32_t JsonObject::CalculateNestDepth(const uint8_t *dataBegin, const uint8_t *dataEnd, int &errCode)
798 {
799 (void)dataBegin;
800 (void)dataEnd;
801 (void)errCode;
802 return 0;
803 }
804
805 JsonObject::JsonObject(const JsonObject &other) = default;
806
807 JsonObject& JsonObject::operator=(const JsonObject &other) = default;
808
809 int JsonObject::Parse(const std::string &inString)
810 {
811 (void)inString;
812 LOGW("[Json][Parse] Json Omit From Compile.");
813 return -E_NOT_PERMIT;
814 }
815
816 int JsonObject::Parse(const std::vector<uint8_t> &inData)
817 {
818 (void)inData;
819 LOGW("[Json][Parse] Json Omit From Compile.");
820 return -E_NOT_PERMIT;
821 }
822
823 int JsonObject::Parse(const uint8_t *dataBegin, const uint8_t *dataEnd)
824 {
825 (void)dataBegin;
826 (void)dataEnd;
827 LOGW("[Json][Parse] Json Omit From Compile.");
828 return -E_NOT_PERMIT;
829 }
830
831 bool JsonObject::IsValid() const
832 {
833 return false;
834 }
835
836 std::string JsonObject::ToString() const
837 {
838 return std::string();
839 }
840
841 bool JsonObject::IsFieldPathExist(const FieldPath &inPath) const
842 {
843 (void)inPath;
844 return false;
845 }
846
847 int JsonObject::GetFieldTypeByFieldPath(const FieldPath &inPath, FieldType &outType) const
848 {
849 (void)inPath;
850 (void)outType;
851 return -E_NOT_PERMIT;
852 }
853
854 int JsonObject::GetFieldValueByFieldPath(const FieldPath &inPath, FieldValue &outValue) const
855 {
856 (void)inPath;
857 (void)outValue;
858 return -E_NOT_PERMIT;
859 }
860
861 int JsonObject::GetSubFieldPath(const FieldPath &inPath, std::set<FieldPath> &outSubPath) const
862 {
863 (void)inPath;
864 (void)outSubPath;
865 return -E_NOT_PERMIT;
866 }
867
868 int JsonObject::GetSubFieldPath(const std::set<FieldPath> &inPath, std::set<FieldPath> &outSubPath) const
869 {
870 (void)inPath;
871 (void)outSubPath;
872 return -E_NOT_PERMIT;
873 }
874
875 int JsonObject::GetSubFieldPathAndType(const FieldPath &inPath, std::map<FieldPath, FieldType> &outSubPathType) const
876 {
877 (void)inPath;
878 (void)outSubPathType;
879 return -E_NOT_PERMIT;
880 }
881
882 int JsonObject::GetSubFieldPathAndType(const std::set<FieldPath> &inPath,
883 std::map<FieldPath, FieldType> &outSubPathType) const
884 {
885 (void)inPath;
886 (void)outSubPathType;
887 return -E_NOT_PERMIT;
888 }
889
890 int JsonObject::GetArraySize(const FieldPath &inPath, uint32_t &outSize) const
891 {
892 (void)inPath;
893 (void)outSize;
894 return -E_NOT_PERMIT;
895 }
896
897 int JsonObject::GetArrayContentOfStringOrStringArray(const FieldPath &inPath,
898 std::vector<std::vector<std::string>> &outContent) const
899 {
900 (void)inPath;
901 (void)outContent;
902 return -E_NOT_PERMIT;
903 }
904
905 int JsonObject::InsertField(const FieldPath &inPath, FieldType inType, const FieldValue &inValue)
906 {
907 (void)inPath;
908 (void)inType;
909 (void)inValue;
910 return -E_NOT_PERMIT;
911 }
912
913 int JsonObject::InsertField(const FieldPath &inPath, const JsonObject &inValue, bool isAppend = false)
914 {
915 (void)inPath;
916 (void)inValue;
917 (void)isAppend;
918 return -E_NOT_PERMIT;
919 }
920
921 int JsonObject::DeleteField(const FieldPath &inPath)
922 {
923 (void)inPath;
924 return -E_NOT_PERMIT;
925 }
926
927 int JsonObject::GetArrayValueByFieldPath(const FieldPath &inPath, JsonObject &outArray) const
928 {
929 (void)inPath;
930 (void)outArray;
931 return -E_NOT_PERMIT;
932 }
933 #endif // OMIT_JSON
934 } // namespace DistributedDB
935