Skip to content

Commit 3aa95b8

Browse files
committed
Merge branch 'allow-escaped-json' into envoy-gloo
2 parents 5a18986 + 6bfec7e commit 3aa95b8

File tree

5 files changed

+42
-2
lines changed

5 files changed

+42
-2
lines changed

include/inja/config.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ struct ParserConfig {
8080
*/
8181
struct RenderConfig {
8282
bool throw_at_missing_includes {true};
83+
bool escape_strings {};
8384
};
8485

8586
} // namespace inja

include/inja/environment.hpp

+5
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ class Environment {
8888
lexer_config.notation = notation;
8989
}
9090

91+
/// Sets the config for rendering strings raw or escaped
92+
void set_escape_strings(bool escape_strings) {
93+
render_config.escape_strings = escape_strings;
94+
}
95+
9196
/// Sets the element notation syntax
9297
void set_search_included_templates_in_files(bool search_in_files) {
9398
parser_config.search_included_templates_in_files = search_in_files;

include/inja/renderer.hpp

+14-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,20 @@ class Renderer : public NodeVisitor {
5555

5656
void print_data(const std::shared_ptr<json> value) {
5757
if (value->is_string()) {
58-
*output_stream << value->get_ref<const json::string_t&>();
58+
std::string val;
59+
if (config.escape_strings) {
60+
// get the value as a dump() to properly escape values
61+
val = value->dump();
62+
63+
// strip the leading and trailing " characters that are added by dump()
64+
// if C++20 is adopted, val.starts_with and val.ends_with would clean this up a bit
65+
val = val.substr(0,1) == "\"" && val.substr(val.length()-1,1) == "\""
66+
? val.substr(1, val.length()-2)
67+
: val;
68+
} else {
69+
val = value->get_ref<const json::string_t&>();
70+
}
71+
*output_stream << val;
5972
} else if (value->is_number_integer()) {
6073
*output_stream << value->get<const json::number_integer_t>();
6174
} else if (value->is_null()) {

single_include/inja/inja.hpp

+16-1
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,7 @@ struct ParserConfig {
906906
*/
907907
struct RenderConfig {
908908
bool throw_at_missing_includes {true};
909+
bool escape_strings {};
909910
};
910911

911912
} // namespace inja
@@ -2150,7 +2151,16 @@ class Renderer : public NodeVisitor {
21502151

21512152
void print_data(const std::shared_ptr<json> value) {
21522153
if (value->is_string()) {
2153-
*output_stream << value->get_ref<const json::string_t&>();
2154+
std::string val;
2155+
if (config.escape_strings) {
2156+
val = value->dump();
2157+
val = val.substr(0,1) == "\"" && val.substr(val.length()-1,1) == "\""
2158+
? val.substr(1, val.length()-2)
2159+
: val;
2160+
} else {
2161+
val = value->get_ref<const json::string_t&>();
2162+
}
2163+
*output_stream << val;
21542164
} else if (value->is_number_integer()) {
21552165
*output_stream << value->get<const json::number_integer_t>();
21562166
} else if (value->is_null()) {
@@ -2803,6 +2813,11 @@ class Environment {
28032813
lexer_config.notation = notation;
28042814
}
28052815

2816+
/// Sets the config for rendering strings raw or escaped
2817+
void set_escape_strings(bool escape_strings) {
2818+
render_config.escape_strings = escape_strings;
2819+
}
2820+
28062821
/// Sets the element notation syntax
28072822
void set_search_included_templates_in_files(bool search_in_files) {
28082823
parser_config.search_included_templates_in_files = search_in_files;

test/test-renderer.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ TEST_CASE("types") {
2121
data["json_pointers"]["example.com"] = "online";
2222
data["json_pointers"]["and/or"] = "slash";
2323
data["json_pointers"]["and~or"] = "tilde";
24+
data["quoted"] = "\"quoted value\"";
2425

2526
SUBCASE("basic") {
2627
CHECK(env.render("", data) == "");
@@ -48,6 +49,11 @@ TEST_CASE("types") {
4849
CHECK(env.render("{{ json_pointers/and~0or }}", data) == "tilde");
4950
env.set_element_notation(inja::ElementNotation::Dot);
5051

52+
CHECK(env.render(R"EOF({"Value":"{{ quoted }}"})EOF", data) == R"EOF({"Value":""quoted value""})EOF");
53+
env.set_escape_strings(true);
54+
CHECK(env.render(R"EOF({"Value":"{{ quoted }}"})EOF", data) == R"EOF({"Value":"\"quoted value\""})EOF");
55+
env.set_escape_strings(false);
56+
5157
CHECK_THROWS_WITH(env.render("{{unknown}}", data), "[inja.exception.render_error] (at 1:3) variable 'unknown' not found");
5258
}
5359

0 commit comments

Comments
 (0)