@@ -68,11 +68,6 @@ def test_create_id
6868 JSON . create_id = 'json_class'
6969 end
7070
71- def test_deep_const_get
72- assert_raise ( ArgumentError ) { JSON . deep_const_get ( 'Nix::Da' ) }
73- assert_equal File ::SEPARATOR , JSON . deep_const_get ( 'File::SEPARATOR' )
74- end
75-
7671 def test_parse
7772 assert_equal [ 1 , 2 , 3 , ] , JSON . parse ( '[ 1, 2, 3 ]' )
7873 end
@@ -91,6 +86,30 @@ def test_fast_generate
9186
9287 def test_pretty_generate
9388 assert_equal "[\n 1,\n 2,\n 3\n ]" , JSON . pretty_generate ( [ 1 , 2 , 3 ] )
89+ assert_equal <<~JSON . strip , JSON . pretty_generate ( { a : { b : "f" } , c : "d" } )
90+ {
91+ "a": {
92+ "b": "f"
93+ },
94+ "c": "d"
95+ }
96+ JSON
97+
98+ # Cause the state to be spilled on the heap.
99+ o = Object . new
100+ def o . to_s
101+ "Object"
102+ end
103+ actual = JSON . pretty_generate ( { a : { b : o } , c : "d" , e : "f" } )
104+ assert_equal <<~JSON . strip , actual
105+ {
106+ "a": {
107+ "b": "Object"
108+ },
109+ "c": "d",
110+ "e": "f"
111+ }
112+ JSON
94113 end
95114
96115 def test_load
@@ -110,7 +129,7 @@ def test_load
110129
111130 def test_load_with_proc
112131 visited = [ ]
113- JSON . load ( '{"foo": [1, 2, 3], "bar": {"baz": "plop"}}' , proc { |o | visited << JSON . dump ( o ) } )
132+ JSON . load ( '{"foo": [1, 2, 3], "bar": {"baz": "plop"}}' , proc { |o | visited << JSON . dump ( o ) ; o } )
114133
115134 expected = [
116135 '"foo"' ,
@@ -138,6 +157,87 @@ def test_load_null
138157 assert_raise ( JSON ::ParserError ) { JSON . load ( '' , nil , :allow_blank => false ) }
139158 end
140159
160+ def test_unsafe_load
161+ string_able_klass = Class . new do
162+ def initialize ( str )
163+ @str = str
164+ end
165+
166+ def to_str
167+ @str
168+ end
169+ end
170+
171+ io_able_klass = Class . new do
172+ def initialize ( str )
173+ @str = str
174+ end
175+
176+ def to_io
177+ StringIO . new ( @str )
178+ end
179+ end
180+
181+ assert_equal @hash , JSON . unsafe_load ( @json )
182+ tempfile = Tempfile . open ( '@json' )
183+ tempfile . write @json
184+ tempfile . rewind
185+ assert_equal @hash , JSON . unsafe_load ( tempfile )
186+ stringio = StringIO . new ( @json )
187+ stringio . rewind
188+ assert_equal @hash , JSON . unsafe_load ( stringio )
189+ string_able = string_able_klass . new ( @json )
190+ assert_equal @hash , JSON . unsafe_load ( string_able )
191+ io_able = io_able_klass . new ( @json )
192+ assert_equal @hash , JSON . unsafe_load ( io_able )
193+ assert_equal nil , JSON . unsafe_load ( nil )
194+ assert_equal nil , JSON . unsafe_load ( '' )
195+ ensure
196+ tempfile . close!
197+ end
198+
199+ def test_unsafe_load_with_proc
200+ visited = [ ]
201+ JSON . unsafe_load ( '{"foo": [1, 2, 3], "bar": {"baz": "plop"}}' , proc { |o | visited << JSON . dump ( o ) ; o } )
202+
203+ expected = [
204+ '"foo"' ,
205+ '1' ,
206+ '2' ,
207+ '3' ,
208+ '[1,2,3]' ,
209+ '"bar"' ,
210+ '"baz"' ,
211+ '"plop"' ,
212+ '{"baz":"plop"}' ,
213+ '{"foo":[1,2,3],"bar":{"baz":"plop"}}' ,
214+ ]
215+ assert_equal expected , visited
216+ end
217+
218+ def test_unsafe_load_default_options
219+ too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
220+ assert JSON . unsafe_load ( too_deep , nil ) . is_a? ( Array )
221+ nan_json = '{ "foo": NaN }'
222+ assert JSON . unsafe_load ( nan_json , nil ) [ 'foo' ] . nan?
223+ assert_equal nil , JSON . unsafe_load ( nil , nil )
224+ t = Time . new ( 2025 , 9 , 3 , 14 , 50 , 0 )
225+ assert_equal t . to_s , JSON . unsafe_load ( JSON ( t ) ) . to_s
226+ end
227+
228+ def test_unsafe_load_with_options
229+ nan_json = '{ "foo": NaN }'
230+ assert_raise ( JSON ::ParserError ) { JSON . unsafe_load ( nan_json , nil , :allow_nan => false ) [ 'foo' ] . nan? }
231+ # make sure it still uses the defaults when something is provided
232+ assert JSON . unsafe_load ( nan_json , nil , :allow_blank => true ) [ 'foo' ] . nan?
233+ end
234+
235+ def test_unsafe_load_null
236+ assert_equal nil , JSON . unsafe_load ( nil , nil , :allow_blank => true )
237+ assert_raise ( TypeError ) { JSON . unsafe_load ( nil , nil , :allow_blank => false ) }
238+ assert_raise ( JSON ::ParserError ) { JSON . unsafe_load ( '' , nil , :allow_blank => false ) }
239+ end
240+
141241 def test_dump
142242 too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
143243 obj = eval ( too_deep )
@@ -174,9 +274,9 @@ def test_dump_in_io
174274 end
175275
176276 def test_dump_should_modify_defaults
177- max_nesting = JSON . dump_default_options [ :max_nesting ]
277+ max_nesting = JSON . _dump_default_options [ :max_nesting ]
178278 dump ( [ ] , StringIO . new , 10 )
179- assert_equal max_nesting , JSON . dump_default_options [ :max_nesting ]
279+ assert_equal max_nesting , JSON . _dump_default_options [ :max_nesting ]
180280 end
181281
182282 def test_JSON
@@ -211,6 +311,12 @@ def test_load_file_with_bad_default_external_encoding
211311 end
212312 end
213313
314+ def test_deprecated_dump_default_options
315+ assert_deprecated_warning ( /dump_default_options/ ) do
316+ JSON . dump_default_options
317+ end
318+ end
319+
214320 private
215321
216322 def with_external_encoding ( encoding )
0 commit comments