Escaping JSON in FreeMaker

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)}"
}

One thought on “Escaping JSON in FreeMaker

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s