Skip to content

Commit 3a8505a

Browse files
committed
JSON.load_file: explictly load the file as UTF-8
Fix: #697 This way even if `Encoding.default_external` is set to a weird value the document will be parsed just fine.
1 parent 4be55b0 commit 3a8505a

File tree

3 files changed

+30
-4
lines changed

3 files changed

+30
-4
lines changed

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Changes
22

3+
* `JSON.load_file` explictly read the file as UTF-8.
4+
35
### 2024-11-06 (2.8.1)
46

57
* Fix the java packages to include the extension.

lib/json/common.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
#frozen_string_literal: true
1+
# frozen_string_literal: true
2+
23
require 'json/version'
34

45
module JSON
@@ -230,8 +231,8 @@ def parse!(source, opts = {})
230231
# parse(File.read(path), opts)
231232
#
232233
# See method #parse.
233-
def load_file(filespec, opts = {})
234-
parse(File.read(filespec), opts)
234+
def load_file(filespec, opts = nil)
235+
parse(File.read(filespec, encoding: Encoding::UTF_8), opts)
235236
end
236237

237238
# :call-seq:
@@ -242,7 +243,7 @@ def load_file(filespec, opts = {})
242243
#
243244
# See method #parse!
244245
def load_file!(filespec, opts = {})
245-
parse!(File.read(filespec), opts)
246+
parse!(File.read(filespec, encoding: Encoding::UTF_8), opts)
246247
end
247248

248249
# :call-seq:

test/json/json_common_interface_test.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# frozen_string_literal: true
2+
23
require_relative 'test_helper'
34
require 'stringio'
45
require 'tempfile'
@@ -189,8 +190,30 @@ def test_load_file_with_option!
189190
test_load_file_with_option_shared(:load_file!)
190191
end
191192

193+
def test_load_file_with_bad_default_external_encoding
194+
data = { "key" => "€" }
195+
temp_file_containing(JSON.dump(data)) do |path|
196+
loaded_data = with_external_encoding(Encoding::US_ASCII) do
197+
JSON.load_file(path)
198+
end
199+
assert_equal data, loaded_data
200+
end
201+
end
202+
192203
private
193204

205+
def with_external_encoding(encoding)
206+
verbose = $VERBOSE
207+
$VERBOSE = nil
208+
previous_encoding = Encoding.default_external
209+
Encoding.default_external = encoding
210+
yield
211+
ensure
212+
verbose = $VERBOSE
213+
Encoding.default_external = previous_encoding
214+
$VERBOSE = verbose
215+
end
216+
194217
def test_load_shared(method_name)
195218
temp_file_containing(@json) do |filespec|
196219
assert_equal JSON.public_send(method_name, filespec), @hash

0 commit comments

Comments
 (0)