Skip to content

Instantly share code, notes, and snippets.

@tniessen
Created March 27, 2022 21:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tniessen/77bd09fca3c15104d4bdfb4ec9f4ba1c to your computer and use it in GitHub Desktop.
Save tniessen/77bd09fca3c15104d4bdfb4ec9f4ba1c to your computer and use it in GitHub Desktop.
Proper JSON escaping for CMake 3.19 and above
# CMake does not support escaping string values for use in JSON. However, it
# does properly escape keys in JSON object literals. We use that fact to escape
# string values by constructing a JSON object with a single named property,
# whose key is the string that we want to escape. Then we strip away all of the
# stringified JSON object except said key.
function(json_esc ret_var val_str)
string(JSON tmp_json SET "{}" "${val_str}" "0")
string(REGEX REPLACE "^\\{[ \t\r\n]*" "" tmp_json "${tmp_json}")
string(REGEX REPLACE "[ \t\r\n]*:[ \t\r\n]*0[ \t\r\n]*\\}$" "" tmp_json "${tmp_json}")
if(NOT "${tmp_json}" MATCHES "^\"[^\n]*\"")
message(FATAL_ERROR "Internal error: unexpected output: '${tmp_json}'")
endif()
set(${ret_var} "${tmp_json}" PARENT_SCOPE)
endfunction()
# The remainder of this file contains tests only.
function(test_json_esc input expected_output)
message(CHECK_START "Test JSON escaping: ${expected_output}")
json_esc(actual_output "${input}")
if("${actual_output}" STREQUAL "${expected_output}")
message(CHECK_PASS "pass")
else()
message(CHECK_FAIL "fail (got ${actual_output})")
endif()
endfunction()
test_json_esc("" "\"\"")
test_json_esc("foo" "\"foo\"")
test_json_esc("\"foo\"" "\"\\\"foo\\\"\"")
test_json_esc("\"foo\n" "\"\\\"foo\\n\"")
test_json_esc("\t.\r.\n.\"[]\\" "\"\\t.\\r.\\n.\\\"[]\\\\\"")
test_json_esc(" abc def " "\" abc def \"")
test_json_esc("{\"foo\": [\"bar\"]}" "\"{\\\"foo\\\": [\\\"bar\\\"]}\"")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment