Browse Source

string(JSON): Add GET_RAW mode

Kyle Edwards 2 months ago
parent
commit
15973ff247

+ 11 - 1
Help/command/string.rst

@@ -46,7 +46,7 @@ Synopsis
 
   `JSON`_
     string(JSON <out-var> [ERROR_VARIABLE <error-var>]
-           {`GET <JSON-GET_>`__ | `TYPE <JSON-TYPE_>`__ | `LENGTH <JSON-LENGTH_>`__ | `REMOVE <JSON-REMOVE_>`__}
+           {`GET <JSON-GET_>`__ | `GET_RAW <JSON-GET-RAW_>`__ | `TYPE <JSON-TYPE_>`__ | `LENGTH <JSON-LENGTH_>`__ | `REMOVE <JSON-REMOVE_>`__}
            <json-string> <member|index> [<member|index> ...])
     string(JSON <out-var> [ERROR_VARIABLE <error-var>]
            `MEMBER <JSON-MEMBER_>`__ <json-string>
@@ -559,6 +559,16 @@ string is passed as a single argument even if it contains semicolons.
   Null elements will be returned as an empty string.
   Number and string types will be returned as strings.
 
+.. signature::
+  string(JSON <out-var> [ERROR_VARIABLE <error-variable>]
+         GET_RAW <json-string> <member|index> [<member|index> ...])
+  :target: JSON-GET-RAW
+
+  Get an element from ``<json-string>`` at the location given
+  by the list of ``<member|index>`` arguments. Similar to
+  `GET <JSON-GET_>`__, but does not convert number, string,
+  boolean, or null elements.
+
 .. signature::
   string(JSON <out-var> [ERROR_VARIABLE <error-variable>]
          TYPE <json-string> <member|index> [<member|index> ...])

+ 4 - 0
Help/release/dev/string-json-improvements.rst

@@ -0,0 +1,4 @@
+string-json-improvements
+------------------------
+
+* The :command:`string(JSON)` command gained a new ``GET_RAW`` mode.

+ 11 - 7
Source/cmStringCommand.cxx

@@ -952,13 +952,13 @@ bool HandleJSONCommand(std::vector<std::string> const& arguments,
     }
 
     auto const& mode = args.PopFront("missing mode argument"_s);
-    if (mode != "GET"_s && mode != "TYPE"_s && mode != "MEMBER"_s &&
-        mode != "LENGTH"_s && mode != "REMOVE"_s && mode != "SET"_s &&
-        mode != "EQUAL"_s) {
-      throw json_error(
-        cmStrCat("got an invalid mode '"_s, mode,
-                 "', expected one of GET, TYPE, MEMBER, LENGTH, REMOVE, SET, "
-                 " EQUAL"_s));
+    if (mode != "GET"_s && mode != "GET_RAW"_s && mode != "TYPE"_s &&
+        mode != "MEMBER"_s && mode != "LENGTH"_s && mode != "REMOVE"_s &&
+        mode != "SET"_s && mode != "EQUAL"_s) {
+      throw json_error(cmStrCat(
+        "got an invalid mode '"_s, mode,
+        "', expected one of GET, GET_RAW, TYPE, MEMBER, LENGTH, REMOVE, SET, "
+        " EQUAL"_s));
     }
 
     auto const& jsonstr = args.PopFront("missing json string argument"_s);
@@ -974,6 +974,10 @@ bool HandleJSONCommand(std::vector<std::string> const& arguments,
         makefile.AddDefinition(*outputVariable, value.asString());
       }
 
+    } else if (mode == "GET_RAW"_s) {
+      auto const& value = ResolvePath(json, args);
+      makefile.AddDefinition(*outputVariable, WriteJson(value));
+
     } else if (mode == "TYPE"_s) {
       auto const& value = ResolvePath(json, args);
       makefile.AddDefinition(*outputVariable, JsonTypeToString(value.type()));

+ 21 - 1
Tests/RunCMake/string/JSON.cmake

@@ -65,6 +65,9 @@ set(json1 [=[
     "false" : false,
     "true" : true
   },
+  "object": {
+    "foo": "bar"
+  },
   "special" : {
     "foo;bar" : "value1",
     ";" : "value2",
@@ -90,6 +93,7 @@ set(json1 [=[
 }
 ]=])
 
+# test GET
 string(JSON result GET "${json1}" foo)
 assert_strequal("${result}" bar)
 string(JSON result GET "${json1}" array 0)
@@ -200,6 +204,22 @@ string(JSON char ERROR_VARIABLE error GET "${unicode}" datalinkescape)
 string(JSON result ERROR_VARIABLE error GET "${unicode}" "${char}")
 assert_strequal_error("${result}" "datalinkescape" "${error}")
 
+# Test GET_RAW
+string(JSON result GET_RAW "${json1}" values null)
+assert_strequal("${result}" null)
+string(JSON result GET_RAW "${json1}" values number)
+assert_strequal("${result}" 5)
+string(JSON result GET_RAW "${json1}" values string)
+assert_strequal("${result}" "\"foo\"")
+string(JSON result GET_RAW "${json1}" values false)
+assert_strequal("${result}" false)
+string(JSON result GET_RAW "${json1}" values true)
+assert_strequal("${result}" true)
+string(JSON result ERROR_VARIABLE error GET_RAW "${json1}" array)
+assert_json_equal("${error}" "${result}" [=[ [5, "val", {"some": "other"}, null] ]=])
+string(JSON result ERROR_VARIABLE error GET_RAW "${json1}" object)
+assert_json_equal("${error}" "${result}" [=[ { "foo": "bar" } ]=])
+
 # Test TYPE
 string(JSON result TYPE "${json1}" types null)
 assert_strequal("${result}" NULL)
@@ -216,7 +236,7 @@ assert_strequal("${result}" OBJECT)
 
 # Test LENGTH
 string(JSON result ERROR_VARIABLE error LENGTH "${json1}")
-assert_strequal("${result}" 5)
+assert_strequal("${result}" 6)
 if(error)
   message(SEND_ERROR "Unexpected error: ${error}")
 endif()

+ 1 - 1
Tests/RunCMake/string/JSONWrongMode-stderr.txt

@@ -1,5 +1,5 @@
 CMake Error at JSONWrongMode\.cmake:1 \(string\):
   string sub-command JSON got an invalid mode 'FOO', expected one of GET,
-  TYPE, MEMBER, LENGTH, REMOVE, SET, EQUAL\.
+  GET_RAW, TYPE, MEMBER, LENGTH, REMOVE, SET, EQUAL\.
 Call Stack \(most recent call first\):
   CMakeLists\.txt:[0-9]+ \(include\)