From 1b6a26e23a43564de2e221f1b123e749bd3403d6 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 7 Nov 2024 17:22:10 +0100 Subject: [PATCH] [ruby/json] JSON.load_file: explictly load the file as UTF-8 Fix: https://github.com/ruby/json/issues/697 This way even if `Encoding.default_external` is set to a weird value the document will be parsed just fine. https://github.com/ruby/json/commit/3a8505a8fa --- ext/json/lib/json/common.rb | 9 +++++---- test/json/json_common_interface_test.rb | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb index 2269896ba8..03aaaa6e7e 100644 --- a/ext/json/lib/json/common.rb +++ b/ext/json/lib/json/common.rb @@ -1,4 +1,5 @@ -#frozen_string_literal: true +# frozen_string_literal: true + require 'json/version' module JSON @@ -230,8 +231,8 @@ module JSON # parse(File.read(path), opts) # # See method #parse. - def load_file(filespec, opts = {}) - parse(File.read(filespec), opts) + def load_file(filespec, opts = nil) + parse(File.read(filespec, encoding: Encoding::UTF_8), opts) end # :call-seq: @@ -242,7 +243,7 @@ module JSON # # See method #parse! def load_file!(filespec, opts = {}) - parse!(File.read(filespec), opts) + parse!(File.read(filespec, encoding: Encoding::UTF_8), opts) end # :call-seq: diff --git a/test/json/json_common_interface_test.rb b/test/json/json_common_interface_test.rb index 6165cc0411..643d3e92ec 100644 --- a/test/json/json_common_interface_test.rb +++ b/test/json/json_common_interface_test.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require_relative 'test_helper' require 'stringio' require 'tempfile' @@ -189,8 +190,30 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase test_load_file_with_option_shared(:load_file!) end + def test_load_file_with_bad_default_external_encoding + data = { "key" => "€" } + temp_file_containing(JSON.dump(data)) do |path| + loaded_data = with_external_encoding(Encoding::US_ASCII) do + JSON.load_file(path) + end + assert_equal data, loaded_data + end + end + private + def with_external_encoding(encoding) + verbose = $VERBOSE + $VERBOSE = nil + previous_encoding = Encoding.default_external + Encoding.default_external = encoding + yield + ensure + verbose = $VERBOSE + Encoding.default_external = previous_encoding + $VERBOSE = verbose + end + def test_load_shared(method_name) temp_file_containing(@json) do |filespec| assert_equal JSON.public_send(method_name, filespec), @hash