Kieran Hunt

Don't interpolate JSON

✦ 2023-11-12

Consider a scenario where you need to produce JSON in an ERB template. Instead of doing this:

{
  "foo": "bar",
  "baz": "<%= something %>"
  "gorp": "zarp"
}

Do this:

<%=
require 'json'

{
  foo: "bar",
  baz: something,
  gorp: "zarp"
}.to_json
%>

But why?

  1. Guaranteed Valid JSON: Starting with a Ruby hash ensures the resulting JSON is valid, eliminating common errors like missing commas or mismatched quotes. Did you notice that there’s a missing trailing comma on the "baz" line?
  2. Build-Time Error Detection: Syntax errors are caught at build time, offering an early warning that prevents issues from surfacing when the JSON is consumed.
  3. Prevention of Unintended JSON Escapes: By directly referencing variables in the hash, there’s no risk of unintentionally injecting invalid JSON due to escaping issues. In the first example, what if something returned ", "zarp": "garble? The object will now have 4 items rather than 3. That’s probably not how the author intended this to work.
  4. Reduced Templating Code: Adopting this approach leads to cleaner code with fewer <%= and %> tags, enhancing readability and maintainability.
  5. Improved Syntax Highlighting: The cleaner structure of using Ruby hashes typically results in better syntax highlighting support in code editors.