Skip to content

Commit 8be58ff

Browse files
etiennebarriebyroot
andcommitted
Add escape: false option to ActiveSupport::JSON.encode
In many contexts you don't need the resuling JSON to be HTML-safe. This both saves a costly operation and renders cleaner JSON. Co-authored-by: Jean Boussier <[email protected]>
1 parent 6204a55 commit 8be58ff

File tree

2 files changed

+18
-3
lines changed

2 files changed

+18
-3
lines changed

activesupport/lib/active_support/json/encoding.rb

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ class << self
2020
# ActiveSupport::JSON.encode({ team: 'rails', players: '36' })
2121
# # => "{\"team\":\"rails\",\"players\":\"36\"}"
2222
#
23-
# Generates JSON that is safe to include in JavaScript as it escapes
24-
# U+2028 (Line Separator) and U+2029 (Paragraph Separator):
23+
# By default, it generates JSON that is safe to include in JavaScript, as
24+
# it escapes U+2028 (Line Separator) and U+2029 (Paragraph Separator):
2525
#
2626
# ActiveSupport::JSON.encode({ key: "\u2028" })
2727
# # => "{\"key\":\"\\u2028\"}"
@@ -32,11 +32,17 @@ class << self
3232
# ActiveSupport::JSON.encode({ key: "<>&" })
3333
# # => "{\"key\":\"\\u003c\\u003e\\u0026\"}"
3434
#
35-
# This can be changed with the +escape_html_entities+ option, or the
35+
# This behavior can be changed with the +escape_html_entities+ option, or the
3636
# global escape_html_entities_in_json configuration option.
3737
#
3838
# ActiveSupport::JSON.encode({ key: "<>&" }, escape_html_entities: false)
3939
# # => "{\"key\":\"<>&\"}"
40+
#
41+
# For performance reasons, you can set the +escape+ option to false,
42+
# which will skip all escaping:
43+
#
44+
# ActiveSupport::JSON.encode({ key: "\u2028<>&" }, escape: false)
45+
# # => "{\"key\":\"\u2028<>&\"}"
4046
def encode(value, options = nil)
4147
if options.nil? || options.empty?
4248
Encoding.encode_without_options(value)
@@ -76,6 +82,8 @@ def encode(value)
7682
end
7783
json = stringify(jsonify(value))
7884

85+
return json unless @options.fetch(:escape, true)
86+
7987
# Rails does more escaping than the JSON gem natively does (we
8088
# escape \u2028 and \u2029 and optionally >, <, & to work around
8189
# certain browser problems).
@@ -162,6 +170,8 @@ def encode(value)
162170

163171
json = CODER.dump(value)
164172

173+
return json unless @options.fetch(:escape, true)
174+
165175
# Rails does more escaping than the JSON gem natively does (we
166176
# escape \u2028 and \u2029 and optionally >, <, & to work around
167177
# certain browser problems).

activesupport/test/json/encoding_test.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ def test_hash_encoding
5252
assert_equal %({\"a\":\"b\",\"c\":\"d\"}), sorted_json(ActiveSupport::JSON.encode(a: :b, c: :d))
5353
end
5454

55+
def test_unicode_escape
56+
assert_equal %{{"\\u2028":"\\u2029"}}, ActiveSupport::JSON.encode("\u2028" => "\u2029")
57+
assert_equal %{{"\u2028":"\u2029"}}, ActiveSupport::JSON.encode({ "\u2028" => "\u2029" }, escape: false)
58+
end
59+
5560
def test_hash_keys_encoding
5661
ActiveSupport.escape_html_entities_in_json = true
5762
assert_equal "{\"\\u003c\\u003e\":\"\\u003c\\u003e\"}", ActiveSupport::JSON.encode("<>" => "<>")

0 commit comments

Comments
 (0)