The ?js_string doesn’t work quite right for JSON since it ends up escaping single-quotes. This isn’t quite right for JSON since it only allows Strings to be specified using double-quotes. Therefore, in order to properly escape Strings in FreeMarker for JSON, you need to write a custom method and add it to the model. Here’s my code for a JSON escaper method:
public class JSONEscape implements TemplateMethodModelEx { @Override public Object exec(List arguments) throws TemplateModelException { if (arguments.size() != 1) { throw new TemplateModelException("jsonescape takes a single parameter"); } return JSONBuilder.escape(arguments.get(0).toString()); } }
The JSONBuilder is a class that I wrote for creating JSON using the builder pattern. However, the escape method looks like this:
public static String escape(String str) { StringBuilder build = new StringBuilder(); escape(str, build); return build.toString(); } public static void escape(String str, StringBuilder build) { char[] ca = str.toCharArray(); for (char c : ca) { switch (c) { case '"': case '\': build.append('\'); build.append(c); break; case 'r': build.append("\r"); break; case 'n': build.append("\n"); break; case 't': build.append("\t"); break; case 'b': build.append("\b"); break; case 'f': build.append("\f"); break; case '/': build.append("\/"); break; default: if (c >> 12]); build.append(HEX_CHARS[(ch >>> 8) & 0xf]); build.append(HEX_CHARS[(ch >>> 4) & 0xf]); build.append(HEX_CHARS[ch & 0xf]); }
Then I add this method to my model and render the template:
model.put("jsonescape", new JSONEscape());
My templates look like this:
{ "foo": "${jsonescape(some.value.here)}" }
0