diff --git a/src/json.hpp b/src/json.hpp index e7e8444f..1e61d5e4 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -1321,6 +1321,72 @@ class basic_json } } + /*! + Escape a string by replacing special characters by a sequence of an + escape character (backslash) and another character. + */ + static string_t escape_string(const string_t& s) + { + // create a result string of at least the size than s + string_t result; + result.reserve(s.size()); + + for (auto c : s) + { + switch (c) + { + // quotation mark + case '"': + { + result.append("\\\"", 2); + break; + } + // reverse solidus + case '\\': + { + result.append("\\\\", 2); + break; + } + // backspace + case '\b': + { + result.append("\\b", 2); + break; + } + // formfeed + case '\f': + { + result.append("\\f", 2); + break; + } + // newline + case '\n': + { + result.append("\\n", 2); + break; + } + // carriage return + case '\r': + { + result.append("\\r", 2); + break; + } + // horizontal tab + case '\t': + { + result.append("\\t", 2); + break; + } + default: + { + result.append(1, c); + } + } + } + + return result; + } + /*! Internal implementation of the serialization function. @@ -1417,7 +1483,7 @@ class basic_json case (value_t::string): { - return string_t("\"") + *m_value.string + "\""; + return string_t("\"") + escape_string(*m_value.string) + "\""; } case (value_t::boolean): diff --git a/test/unit.cpp b/test/unit.cpp index 3c0d8185..8cbd6ea9 100644 --- a/test/unit.cpp +++ b/test/unit.cpp @@ -11,6 +11,19 @@ using nlohmann::json; TEST_CASE() { + CHECK(json::escape_string("\\") == "\\\\"); + CHECK(json::escape_string("\"") == "\\\""); + CHECK(json::escape_string("\n") == "\\n"); + CHECK(json::escape_string("\r") == "\\r"); + CHECK(json::escape_string("\f") == "\\f"); + CHECK(json::escape_string("\b") == "\\b"); + CHECK(json::escape_string("\t") == "\\t"); + + { + json j = "AC/DC"; + CHECK(j.dump() == "\"AC/DC\""); + } + { json j = {1, 2, 3, 4}; std::cerr << j << std::endl;