diff --git a/Help/command/string.rst b/Help/command/string.rst index ae138e8788..b369f0282c 100644 --- a/Help/command/string.rst +++ b/Help/command/string.rst @@ -46,7 +46,7 @@ Synopsis `JSON`_ string(JSON [ERROR_VARIABLE ] - {`GET `__ | `TYPE `__ | `LENGTH `__ | `REMOVE `__} + {`GET `__ | `GET_RAW `__ | `TYPE `__ | `LENGTH `__ | `REMOVE `__} [ ...]) string(JSON [ERROR_VARIABLE ] `MEMBER `__ @@ -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 [ERROR_VARIABLE ] + GET_RAW [ ...]) + :target: JSON-GET-RAW + + Get an element from ```` at the location given + by the list of ```` arguments. Similar to + `GET `__, but does not convert number, string, + boolean, or null elements. + .. signature:: string(JSON [ERROR_VARIABLE ] TYPE [ ...]) diff --git a/Help/release/dev/string-json-improvements.rst b/Help/release/dev/string-json-improvements.rst new file mode 100644 index 0000000000..4fa37a2bc2 --- /dev/null +++ b/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. diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index 1631b0208a..8116153c5d 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -952,13 +952,13 @@ bool HandleJSONCommand(std::vector 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 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())); diff --git a/Tests/RunCMake/string/JSON.cmake b/Tests/RunCMake/string/JSON.cmake index 255c16a564..365fc474f2 100644 --- a/Tests/RunCMake/string/JSON.cmake +++ b/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() diff --git a/Tests/RunCMake/string/JSONWrongMode-stderr.txt b/Tests/RunCMake/string/JSONWrongMode-stderr.txt index 5ef90f42cd..5a7ff6b041 100644 --- a/Tests/RunCMake/string/JSONWrongMode-stderr.txt +++ b/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\)