xref: /openbmc/phosphor-power/json_parser_utils.hpp (revision f1845c0621324fc8435a8e29377f0b1306e636b7)
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