开发者

How to escape json strings in freemarker

We are building a restful api using Spring MVC and freemarker as the templating language. We have chosen to build json responses in the freemarker

Example freemarker.ftl:

{
"field1" : "${response.value1}",
"field2" : "${response.value2}"
}

We get a problem when the strings in the values contain quotation marks (or any of the other characters in the JSON syntax).

The question: How can I escape these strings using freemarker?

We have looked at ?xml or ?html but they do not cover all relevant characters (such as \).

EDIT: ?js_string will escape the string to comform with JavaScript. And since JSON is based on JavaScript (JavaScript Object Notation), it will work.

EDIT2: In case a single-quote pops up, ?js_string will escape it which again leads to invalid JSON. T开发者_如何学Gohe hotfix for it is:

${variable?js_string?replace("\\'", "\'")} 

and if you really want to be picky:

${variable?js_string?replace("\\'", "\'")?replace("\\>",">")}

Alternatively if you use Spring: http://www.springsurf.org/sites/1.0.0.M3/spring-webscripts/spring-webscripts-documentation/reference/html-single/index.html#js-api-index-org.springframework.extensions.webscripts.json.jsonutils


You're looking for the ?js_string operator.

{
"field1" : "${response.value1?js_string}",
"field2" : "${response.value2?js_string}"
}

That will take care of escaping quotes, backslashes, et. al in order to make your JS happy.

Edit: I just saw that they introduced a ?json_string operator in Freemarker 2.3.19. See here for exactly how it works. And there was much rejoicing...


Use a FreeMarker macro to combine all of the answers above, while making the template more readable and maintainable:

<#macro json_string string>${string?js_string?replace("\\'", "\'")?replace("\\>", ">")}</#macro>
{
"field1" : "<@json_string "${response.value1}"/>",
"field2" : "<@json_string "${response.value2}"/>"
}

If you want to reuse the macro in multiple templates, put it in its own file and include the file instead of duplicating the macro:

<#include "/path/to/macro.ftl">


Starting from FreeMarker 2.3.32, it's much easier, as ?c now quotes strings:

{
"field1" : ${response.value1?c},
"field2" : ${response.value2?c}
}

Note that there are no quotes around the ${...}! That's the point; the ?c puts them there if the value is a string (as opposed to a number or a boolean, which are formatted without adding quotation marks).

Before 2.3.32 the above terminates with error, as string input wasn't allowed by ?c, only numbers and booleans.

Starting from 2.3.32, instead of ?c, you can also use ?cn, which stands for "?c nullable". Then if the value is missing/null, it will output null, without the quotes. So you don't have to complicate the template with printing quotes conditionally either.

Also, It's a good idea to set the c_format setting to "JSON", or "JavaScript or JSON". (Or, if you set the incompatible_improvements configuration setting to 2.3.32 or higher anyway, the last will be the default.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜