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 #ifndef JSON_OBJECT_H 17 #define JSON_OBJECT_H 18 19 #include <map> 20 #include <set> 21 #include <string> 22 #include <vector> 23 #ifndef OMIT_JSON 24 #include <json/json.h> 25 #endif 26 #include "db_types.h" 27 28 namespace DistributedDB { 29 // JsonObject is the abstraction of JsonString, it hides the JsonLib that we use and other messy details. 30 // JsonObject do not support concurrence inherently, use it locally or under mutex protection. 31 class JsonObject final { 32 public: 33 // Set max allowed nest depth and return the value before set. 34 static uint32_t SetMaxNestDepth(uint32_t nestDepth); 35 36 // Calculate nest depth when json string is legal or estimate depth by legal part from illegal json. 37 static uint32_t CalculateNestDepth(const std::string &inString, int &errCode); 38 static uint32_t CalculateNestDepth(const uint8_t *dataBegin, const uint8_t *dataEnd, int &errCode); 39 40 // Support default constructor, copy constructor and copy assignment 41 JsonObject() = default; 42 ~JsonObject() = default; 43 JsonObject(const JsonObject &); 44 JsonObject& operator=(const JsonObject &); 45 46 explicit JsonObject(const Json::Value &value); 47 48 // Should be called on an invalid JsonObject, create new JsonObject if need to reparse 49 // Require the type of the root to be JsonObject, otherwise parse fail 50 int Parse(const std::string &inString); 51 int Parse(const std::vector<uint8_t> &inData); // Whether ends with '\0' in vector is OK 52 53 // The end refer to the byte after the last valid byte 54 int Parse(const uint8_t *dataBegin, const uint8_t *dataEnd); 55 56 bool IsValid() const; 57 58 // Unnecessary spacing will be removed and fieldName resorted by lexicographical order 59 std::string ToString() const; 60 61 bool IsFieldPathExist(const FieldPath &inPath) const; 62 int GetFieldTypeByFieldPath(const FieldPath &inPath, FieldType &outType) const; 63 int GetFieldValueByFieldPath(const FieldPath &inPath, FieldValue &outValue) const; 64 65 int GetObjectArrayByFieldPath(const FieldPath &inPath, std::vector<JsonObject> &outArray) const; 66 int GetStringArrayByFieldPath(const FieldPath &inPath, std::vector<std::string> &outArray) const; 67 68 int GetObjectByFieldPath(const FieldPath &inPath, JsonObject &outObj) const; 69 70 // An empty fieldPath indicate the root, the outSubPath should be empty before call, we will not empty it at first. 71 // If inPath is of multiple path, then outSubPath is combination of result of each inPath. 72 int GetSubFieldPath(const FieldPath &inPath, std::set<FieldPath> &outSubPath) const; 73 int GetSubFieldPath(const std::set<FieldPath> &inPath, std::set<FieldPath> &outSubPath) const; 74 int GetSubFieldPathAndType(const FieldPath &inPath, std::map<FieldPath, FieldType> &outSubPathType) const; 75 int GetSubFieldPathAndType(const std::set<FieldPath> &inPath, std::map<FieldPath, FieldType> &outSubPathType) const; 76 77 // If inPath not refer to an array, return error. 78 int GetArraySize(const FieldPath &inPath, uint32_t &outSize) const; 79 80 // If inPath not refer to an array, return error. If not all members are string or array type, return error. 81 // If array-type member is empty, ignore. If not all members of the array-type member are string, return error. 82 int GetArrayContentOfStringOrStringArray(const FieldPath &inPath, 83 std::vector<std::vector<std::string>> &outContent) const; 84 85 // Can be called no matter JsonObject valid or not. Invalid turn into valid after call(insert on invalid never fail 86 // if parameter is valid). An empty inPath is not allowed. LEAF_FIELD_ARRAY and INTERNAL_FIELD_OBJECT is not 87 // supported. infinite double is not support. inValue is ignored for LEAF_FIELD_NULL. 88 // When inPath already exist, append value if it's an arrayObject, otherwise returns -E_JSON_INSERT_PATH_EXIST 89 // if nearest path ends with type not object, rets -E_JSON_INSERT_PATH_CONFLICT. 90 // Otherwise, insert field as well as filling up intermediate field, then returns E_OK; 91 // isAppend: when it's true, append inValue as path is an arrayObject if path not exist. 92 int InsertField(const FieldPath &inPath, FieldType inType, const FieldValue &inValue, bool isAppend = false); 93 94 // Add json object to an array field. should be called on an valid JsonObject. Never turn into invalid after call. 95 // If inPath not refer to an array, return error. 96 int InsertField(const FieldPath &inPath, const JsonObject &inValue, bool isAppend = false); 97 98 // Should be called on an valid JsonObject. Never turn into invalid after call. An empty inPath is not allowed. 99 // If inPath not exist, returns -E_JSON_DELETE_PATH_NOT_FOUND. Otherwise, delete field from its parent returns E_OK; 100 int DeleteField(const FieldPath &inPath); 101 private: 102 #ifndef OMIT_JSON 103 // Auxiliary Method: If inPath not refer to an array, return error. If not all members are string, return error. 104 int GetStringArrayContentByJsonValue(const Json::Value &value, std::vector<std::string> &outStringArray) const; 105 106 // Common Type Judgement Logic 107 int GetFieldTypeByJsonValue(const Json::Value &value, FieldType &outType) const; 108 109 // Return E_OK if JsonValueNode found at exact the path, otherwise not E_OK 110 const Json::Value &GetJsonValueByFieldPath(const FieldPath &inPath, int &errCode) const; 111 112 // REQUIRE: JsonObject is valid(Root value is object type). 113 // If inPath empty(means root), set exact and nearest to root value and nearDepth to 0, then ret E_OK; 114 // If JsonValue exist at exact path, set exact to this JsonValue, set nearest to its parent JsonValue, set nearDepth 115 // to the depth of this parent JsonValue, then ret E_OK; 116 // If exact path no exist, set exact to nullptr, set nearest to nearest JsonValue that can be found, set nearDepth 117 // to the depth of this nearest JsonValue, then ret -E_NOT_FOUND; 118 int LocateJsonValueByFieldPath(const FieldPath &inPath, Json::Value *&exact, 119 Json::Value *&nearest, uint32_t &nearDepth); 120 121 // create if path not exist 122 int MoveToPath(const FieldPath &inPath, Json::Value *&exact, Json::Value *&nearest); 123 124 static uint32_t maxNestDepth_; 125 126 bool isValid_ = false; 127 Json::Value value_; 128 #endif 129 }; 130 } // namespace DistributedDB 131 #endif // JSON_OBJECT_H