138f85004SShawn McCarney /** 238f85004SShawn McCarney * Copyright © 2025 IBM Corporation 338f85004SShawn McCarney * 438f85004SShawn McCarney * Licensed under the Apache License, Version 2.0 (the "License"); 538f85004SShawn McCarney * you may not use this file except in compliance with the License. 638f85004SShawn McCarney * You may obtain a copy of the License at 738f85004SShawn McCarney * 838f85004SShawn McCarney * http://www.apache.org/licenses/LICENSE-2.0 938f85004SShawn McCarney * 1038f85004SShawn McCarney * Unless required by applicable law or agreed to in writing, software 1138f85004SShawn McCarney * distributed under the License is distributed on an "AS IS" BASIS, 1238f85004SShawn McCarney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1338f85004SShawn McCarney * See the License for the specific language governing permissions and 1438f85004SShawn McCarney * limitations under the License. 1538f85004SShawn McCarney */ 1638f85004SShawn McCarney #pragma once 1738f85004SShawn McCarney 1838f85004SShawn McCarney #include <nlohmann/json.hpp> 1938f85004SShawn McCarney 2038f85004SShawn McCarney #include <cstdint> 21*f1845c06SShawn McCarney #include <map> 2238f85004SShawn McCarney #include <stdexcept> 2338f85004SShawn McCarney #include <string> 2438f85004SShawn McCarney #include <vector> 2538f85004SShawn McCarney 2638f85004SShawn McCarney /** 2738f85004SShawn McCarney * @namespace json_parser_utils 2838f85004SShawn McCarney * 2938f85004SShawn McCarney * Contains utility functions for parsing JSON data. 30*f1845c06SShawn McCarney * 31*f1845c06SShawn McCarney * ## Variables 32*f1845c06SShawn McCarney * The parsing functions support optional usage of variables. JSON string values 33*f1845c06SShawn McCarney * can contain one or more variables. A variable is specified using the format 34*f1845c06SShawn McCarney * `${variable_name}`. A variables map is specified to parsing functions that 35*f1845c06SShawn McCarney * provides the variable values. Any variable in a JSON string value will be 36*f1845c06SShawn McCarney * replaced by the variable value. 37*f1845c06SShawn McCarney * 38*f1845c06SShawn McCarney * Variables can only appear in a JSON string value. The parsing functions for 39*f1845c06SShawn McCarney * other data types, such as integer and double, support a string value if it 40*f1845c06SShawn McCarney * contains a variable. After variable expansion, the string is converted to the 41*f1845c06SShawn McCarney * expected data type. 4238f85004SShawn McCarney */ 4338f85004SShawn McCarney namespace phosphor::power::json_parser_utils 4438f85004SShawn McCarney { 4538f85004SShawn McCarney 4638f85004SShawn McCarney /** 47*f1845c06SShawn McCarney * Empty variables map used as a default value for parsing functions. 48*f1845c06SShawn McCarney */ 49*f1845c06SShawn McCarney extern const std::map<std::string, std::string> NO_VARIABLES; 50*f1845c06SShawn McCarney 51*f1845c06SShawn McCarney /** 5238f85004SShawn McCarney * Returns the specified property of the specified JSON element. 5338f85004SShawn McCarney * 5438f85004SShawn McCarney * Throws an invalid_argument exception if the property does not exist. 5538f85004SShawn McCarney * 5638f85004SShawn McCarney * @param element JSON element 5738f85004SShawn McCarney * @param property property name 5838f85004SShawn McCarney */ 5938f85004SShawn McCarney #pragma GCC diagnostic push 6038f85004SShawn McCarney #if __GNUC__ >= 13 6138f85004SShawn McCarney #pragma GCC diagnostic ignored "-Wdangling-reference" 6238f85004SShawn McCarney #endif 6338f85004SShawn McCarney inline const nlohmann::json& getRequiredProperty(const nlohmann::json& element, 6438f85004SShawn McCarney const std::string& property) 6538f85004SShawn McCarney { 6638f85004SShawn McCarney auto it = element.find(property); 6738f85004SShawn McCarney if (it == element.end()) 6838f85004SShawn McCarney { 6938f85004SShawn McCarney throw std::invalid_argument{"Required property missing: " + property}; 7038f85004SShawn McCarney } 7138f85004SShawn McCarney return *it; 7238f85004SShawn McCarney } 7338f85004SShawn McCarney #pragma GCC diagnostic pop 7438f85004SShawn McCarney 7538f85004SShawn McCarney /** 7638f85004SShawn McCarney * Parses a JSON element containing a bit position (from 0-7). 7738f85004SShawn McCarney * 7838f85004SShawn McCarney * Returns the corresponding C++ uint8_t value. 7938f85004SShawn McCarney * 8038f85004SShawn McCarney * Throws an exception if parsing fails. 8138f85004SShawn McCarney * 8238f85004SShawn McCarney * @param element JSON element 83*f1845c06SShawn McCarney * @param variables variables map used to expand variables in element value 8438f85004SShawn McCarney * @return uint8_t value 8538f85004SShawn McCarney */ 86*f1845c06SShawn McCarney uint8_t parseBitPosition( 87*f1845c06SShawn McCarney const nlohmann::json& element, 88*f1845c06SShawn McCarney const std::map<std::string, std::string>& variables = NO_VARIABLES); 8938f85004SShawn McCarney 9038f85004SShawn McCarney /** 9138f85004SShawn McCarney * Parses a JSON element containing a bit value (0 or 1). 9238f85004SShawn McCarney * 9338f85004SShawn McCarney * Returns the corresponding C++ uint8_t value. 9438f85004SShawn McCarney * 9538f85004SShawn McCarney * Throws an exception if parsing fails. 9638f85004SShawn McCarney * 9738f85004SShawn McCarney * @param element JSON element 98*f1845c06SShawn McCarney * @param variables variables map used to expand variables in element value 9938f85004SShawn McCarney * @return uint8_t value 10038f85004SShawn McCarney */ 101*f1845c06SShawn McCarney uint8_t parseBitValue( 102*f1845c06SShawn McCarney const nlohmann::json& element, 103*f1845c06SShawn McCarney const std::map<std::string, std::string>& variables = NO_VARIABLES); 10438f85004SShawn McCarney 10538f85004SShawn McCarney /** 10638f85004SShawn McCarney * Parses a JSON element containing a boolean. 10738f85004SShawn McCarney * 10838f85004SShawn McCarney * Returns the corresponding C++ boolean value. 10938f85004SShawn McCarney * 11038f85004SShawn McCarney * Throws an exception if parsing fails. 11138f85004SShawn McCarney * 11238f85004SShawn McCarney * @param element JSON element 113*f1845c06SShawn McCarney * @param variables variables map used to expand variables in element value 11438f85004SShawn McCarney * @return boolean value 11538f85004SShawn McCarney */ 116*f1845c06SShawn McCarney bool parseBoolean( 117*f1845c06SShawn McCarney const nlohmann::json& element, 118*f1845c06SShawn McCarney const std::map<std::string, std::string>& variables = NO_VARIABLES); 11938f85004SShawn McCarney 12038f85004SShawn McCarney /** 12138f85004SShawn McCarney * Parses a JSON element containing a double (floating point number). 12238f85004SShawn McCarney * 12338f85004SShawn McCarney * Returns the corresponding C++ double value. 12438f85004SShawn McCarney * 12538f85004SShawn McCarney * Throws an exception if parsing fails. 12638f85004SShawn McCarney * 12738f85004SShawn McCarney * @param element JSON element 128*f1845c06SShawn McCarney * @param variables variables map used to expand variables in element value 12938f85004SShawn McCarney * @return double value 13038f85004SShawn McCarney */ 131*f1845c06SShawn McCarney double parseDouble( 132*f1845c06SShawn McCarney const nlohmann::json& element, 133*f1845c06SShawn McCarney const std::map<std::string, std::string>& variables = NO_VARIABLES); 13438f85004SShawn McCarney 13538f85004SShawn McCarney /** 13638f85004SShawn McCarney * Parses a JSON element containing a byte value expressed as a hexadecimal 13738f85004SShawn McCarney * string. 13838f85004SShawn McCarney * 13938f85004SShawn McCarney * The JSON number data type does not support the hexadecimal format. For this 140*f1845c06SShawn McCarney * reason, a hexadecimal byte value is stored in a JSON string. 14138f85004SShawn McCarney * 14238f85004SShawn McCarney * Returns the corresponding C++ uint8_t value. 14338f85004SShawn McCarney * 14438f85004SShawn McCarney * Throws an exception if parsing fails. 14538f85004SShawn McCarney * 14638f85004SShawn McCarney * @param element JSON element 147*f1845c06SShawn McCarney * @param variables variables map used to expand variables in element value 14838f85004SShawn McCarney * @return uint8_t value 14938f85004SShawn McCarney */ 150*f1845c06SShawn McCarney uint8_t parseHexByte( 151*f1845c06SShawn McCarney const nlohmann::json& element, 152*f1845c06SShawn McCarney const std::map<std::string, std::string>& variables = NO_VARIABLES); 15338f85004SShawn McCarney 15438f85004SShawn McCarney /** 15538f85004SShawn McCarney * Parses a JSON element containing an array of byte values expressed as a 15638f85004SShawn McCarney * hexadecimal strings. 15738f85004SShawn McCarney * 15838f85004SShawn McCarney * Returns the corresponding C++ uint8_t values. 15938f85004SShawn McCarney * 16038f85004SShawn McCarney * Throws an exception if parsing fails. 16138f85004SShawn McCarney * 16238f85004SShawn McCarney * @param element JSON element 163*f1845c06SShawn McCarney * @param variables variables map used to expand variables in element value 16438f85004SShawn McCarney * @return vector of uint8_t 16538f85004SShawn McCarney */ 166*f1845c06SShawn McCarney std::vector<uint8_t> parseHexByteArray( 167*f1845c06SShawn McCarney const nlohmann::json& element, 168*f1845c06SShawn McCarney const std::map<std::string, std::string>& variables = NO_VARIABLES); 16938f85004SShawn McCarney 17038f85004SShawn McCarney /** 17138f85004SShawn McCarney * Parses a JSON element containing an 8-bit signed integer. 17238f85004SShawn McCarney * 17338f85004SShawn McCarney * Returns the corresponding C++ int8_t value. 17438f85004SShawn McCarney * 17538f85004SShawn McCarney * Throws an exception if parsing fails. 17638f85004SShawn McCarney * 17738f85004SShawn McCarney * @param element JSON element 178*f1845c06SShawn McCarney * @param variables variables map used to expand variables in element value 17938f85004SShawn McCarney * @return int8_t value 18038f85004SShawn McCarney */ 181*f1845c06SShawn McCarney int8_t parseInt8( 182*f1845c06SShawn McCarney const nlohmann::json& element, 183*f1845c06SShawn McCarney const std::map<std::string, std::string>& variables = NO_VARIABLES); 184*f1845c06SShawn McCarney 185*f1845c06SShawn McCarney /** 186*f1845c06SShawn McCarney * Parses a JSON element containing an integer. 187*f1845c06SShawn McCarney * 188*f1845c06SShawn McCarney * Returns the corresponding C++ int value. 189*f1845c06SShawn McCarney * 190*f1845c06SShawn McCarney * Throws an exception if parsing fails. 191*f1845c06SShawn McCarney * 192*f1845c06SShawn McCarney * @param element JSON element 193*f1845c06SShawn McCarney * @param variables variables map used to expand variables in element value 194*f1845c06SShawn McCarney * @return integer value 195*f1845c06SShawn McCarney */ 196*f1845c06SShawn McCarney int parseInteger( 197*f1845c06SShawn McCarney const nlohmann::json& element, 198*f1845c06SShawn McCarney const std::map<std::string, std::string>& variables = NO_VARIABLES); 19938f85004SShawn McCarney 20038f85004SShawn McCarney /** 20138f85004SShawn McCarney * Parses a JSON element containing a string. 20238f85004SShawn McCarney * 20338f85004SShawn McCarney * Returns the corresponding C++ string. 20438f85004SShawn McCarney * 20538f85004SShawn McCarney * Throws an exception if parsing fails. 20638f85004SShawn McCarney * 20738f85004SShawn McCarney * @param element JSON element 20838f85004SShawn McCarney * @param isEmptyValid indicates whether an empty string value is valid 209*f1845c06SShawn McCarney * @param variables variables map used to expand variables in element value 21038f85004SShawn McCarney * @return string value 21138f85004SShawn McCarney */ 212*f1845c06SShawn McCarney std::string parseString( 213*f1845c06SShawn McCarney const nlohmann::json& element, bool isEmptyValid = false, 214*f1845c06SShawn McCarney const std::map<std::string, std::string>& variables = NO_VARIABLES); 21538f85004SShawn McCarney 21638f85004SShawn McCarney /** 21738f85004SShawn McCarney * Parses a JSON element containing an 8-bit unsigned integer. 21838f85004SShawn McCarney * 21938f85004SShawn McCarney * Returns the corresponding C++ uint8_t value. 22038f85004SShawn McCarney * 22138f85004SShawn McCarney * Throws an exception if parsing fails. 22238f85004SShawn McCarney * 22338f85004SShawn McCarney * @param element JSON element 224*f1845c06SShawn McCarney * @param variables variables map used to expand variables in element value 22538f85004SShawn McCarney * @return uint8_t value 22638f85004SShawn McCarney */ 227*f1845c06SShawn McCarney uint8_t parseUint8( 228*f1845c06SShawn McCarney const nlohmann::json& element, 229*f1845c06SShawn McCarney const std::map<std::string, std::string>& variables = NO_VARIABLES); 23038f85004SShawn McCarney 23138f85004SShawn McCarney /** 23238f85004SShawn McCarney * Parses a JSON element containing an unsigned integer. 23338f85004SShawn McCarney * 23438f85004SShawn McCarney * Returns the corresponding C++ unsigned int value. 23538f85004SShawn McCarney * 23638f85004SShawn McCarney * Throws an exception if parsing fails. 23738f85004SShawn McCarney * 23838f85004SShawn McCarney * @param element JSON element 239*f1845c06SShawn McCarney * @param variables variables map used to expand variables in element value 24038f85004SShawn McCarney * @return unsigned int value 24138f85004SShawn McCarney */ 242*f1845c06SShawn McCarney unsigned int parseUnsignedInteger( 243*f1845c06SShawn McCarney const nlohmann::json& element, 244*f1845c06SShawn McCarney const std::map<std::string, std::string>& variables = NO_VARIABLES); 24538f85004SShawn McCarney 24638f85004SShawn McCarney /** 24738f85004SShawn McCarney * Verifies that the specified JSON element is a JSON array. 24838f85004SShawn McCarney * 24938f85004SShawn McCarney * Throws an invalid_argument exception if the element is not an array. 25038f85004SShawn McCarney * 25138f85004SShawn McCarney * @param element JSON element 25238f85004SShawn McCarney */ 25338f85004SShawn McCarney inline void verifyIsArray(const nlohmann::json& element) 25438f85004SShawn McCarney { 25538f85004SShawn McCarney if (!element.is_array()) 25638f85004SShawn McCarney { 25738f85004SShawn McCarney throw std::invalid_argument{"Element is not an array"}; 25838f85004SShawn McCarney } 25938f85004SShawn McCarney } 26038f85004SShawn McCarney 26138f85004SShawn McCarney /** 26238f85004SShawn McCarney * Verifies that the specified JSON element is a JSON object. 26338f85004SShawn McCarney * 26438f85004SShawn McCarney * Throws an invalid_argument exception if the element is not an object. 26538f85004SShawn McCarney * 26638f85004SShawn McCarney * @param element JSON element 26738f85004SShawn McCarney */ 26838f85004SShawn McCarney inline void verifyIsObject(const nlohmann::json& element) 26938f85004SShawn McCarney { 27038f85004SShawn McCarney if (!element.is_object()) 27138f85004SShawn McCarney { 27238f85004SShawn McCarney throw std::invalid_argument{"Element is not an object"}; 27338f85004SShawn McCarney } 27438f85004SShawn McCarney } 27538f85004SShawn McCarney 27638f85004SShawn McCarney /** 27738f85004SShawn McCarney * Verifies that the specified JSON element contains the expected number of 27838f85004SShawn McCarney * properties. 27938f85004SShawn McCarney * 28038f85004SShawn McCarney * Throws an invalid_argument exception if the element contains a different 28138f85004SShawn McCarney * number of properties. This indicates the element contains an invalid 28238f85004SShawn McCarney * property. 28338f85004SShawn McCarney * 28438f85004SShawn McCarney * @param element JSON element 28538f85004SShawn McCarney * @param expectedCount expected number of properties in element 28638f85004SShawn McCarney */ 28738f85004SShawn McCarney inline void verifyPropertyCount(const nlohmann::json& element, 28838f85004SShawn McCarney unsigned int expectedCount) 28938f85004SShawn McCarney { 29038f85004SShawn McCarney if (element.size() != expectedCount) 29138f85004SShawn McCarney { 29238f85004SShawn McCarney throw std::invalid_argument{"Element contains an invalid property"}; 29338f85004SShawn McCarney } 29438f85004SShawn McCarney } 29538f85004SShawn McCarney 296*f1845c06SShawn McCarney namespace internal 297*f1845c06SShawn McCarney { 298*f1845c06SShawn McCarney 299*f1845c06SShawn McCarney /** 300*f1845c06SShawn McCarney * Expands any variables that appear in the specified string value. 301*f1845c06SShawn McCarney * 302*f1845c06SShawn McCarney * Does nothing if the variables map is empty or the value contains no 303*f1845c06SShawn McCarney * variables. 304*f1845c06SShawn McCarney * 305*f1845c06SShawn McCarney * Throws an invalid_argument exception if a variable occurs in the value that 306*f1845c06SShawn McCarney * does not exist in the variables map. 307*f1845c06SShawn McCarney * 308*f1845c06SShawn McCarney * @param value string value in which to perform variable expansion 309*f1845c06SShawn McCarney * @param variables variables map containing variable values 310*f1845c06SShawn McCarney */ 311*f1845c06SShawn McCarney void expandVariables(std::string& value, 312*f1845c06SShawn McCarney const std::map<std::string, std::string>& variables); 313*f1845c06SShawn McCarney 314*f1845c06SShawn McCarney } // namespace internal 315*f1845c06SShawn McCarney 31638f85004SShawn McCarney } // namespace phosphor::power::json_parser_utils 317