Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. The 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

like image 738
Skurpi Avatar asked Jun 17 '11 08:06

Skurpi


People also ask

How do you escape characters in FreeMarker?

esc creates a markup output value out of a string value by escaping all special characters in it.

How do you insert a line break in FreeMarker?

Learn more. Show activity on this post. In my code I am using "\n" for line breaks. It was suggested that I need to avoid "\n" because this is different for different OS (UNIX, windows and MAC) and each operating system would interpret this character differently.

What is FreeMarker template language?

FreeMarker is a template engine, written in Java, and maintained by the Apache Foundation.

How do I print a value in FreeMarker?

For example, if you create a variable called "foo" in the template, you can print its value with ${foo} . If, coincidently, there's a variable called "foo" in the data-model too, the variable created in the template will hide (not overwrite!)


2 Answers

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...

like image 163
stevevls Avatar answered Sep 21 '22 12:09

stevevls


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">
like image 43
Kevin Condon Avatar answered Sep 23 '22 12:09

Kevin Condon