json
Advanced tools
+8
-0
@@ -5,2 +5,10 @@ # Changes | ||
| ### 2026-07-12 (2.21.0) | ||
| * `JSON.generate` now accept a `sort_keys` option, which takes either a boolean or a block. | ||
| * Added `#empty?` and `#partial_value?` methods on `JSON::ResumableParser`. | ||
| * Numerous correctness and performance fixes for `JSON::ResumableParser`. | ||
| * Avoid triggering Ruby's `float out of range` warning when parsing out of range numbers. | ||
| * Declare C types with Ruby 4.1 `RUBY_TYPED_THREAD_SAFE_FREE`. | ||
| ### 2026-06-23 (2.20.0) | ||
@@ -7,0 +15,0 @@ |
@@ -34,2 +34,6 @@ #ifndef _JSON_H_ | ||
| #ifndef RUBY_TYPED_THREAD_SAFE_FREE | ||
| #define RUBY_TYPED_THREAD_SAFE_FREE RUBY_TYPED_FREE_IMMEDIATELY | ||
| #endif | ||
| #ifndef UNDEF_P | ||
@@ -36,0 +40,0 @@ #define UNDEF_P(val) (val == Qundef) |
+5
-1
@@ -411,3 +411,2 @@ # frozen_string_literal: true | ||
| # used for indentation; defaults to the empty \String, <tt>''</tt>; | ||
| # defaults to the empty \String, <tt>''</tt>; | ||
| # has no effect unless options +array_nl+ or +object_nl+ specify newlines. | ||
@@ -420,2 +419,7 @@ # - Option +space+ (\String) specifies a string (usually a space) to be | ||
| # defaults to the empty \String, <tt>''</tt>. | ||
| # - Option +sort_keys+ (boolean or \Proc) controls whether and how the keys of a | ||
| # hash are sorted when generating the output; defaults to <tt>false</tt>. | ||
| # When +true+, keys are sorted lexicographically. When a \Proc, it receives | ||
| # the entire \Hash and must return a \Hash with its pairs in the desired | ||
| # order, allowing for arbitrary sort orders. | ||
| # | ||
@@ -422,0 +426,0 @@ # In this example, +obj+ is used first to generate the shortest |
@@ -158,2 +158,11 @@ # frozen_string_literal: true | ||
| old, $VERBOSE = $VERBOSE, nil | ||
| # The default proc used when the +sort_keys+ generation option is +true+. | ||
| # It returns a new hash with the entries sorted by their keys. | ||
| sort_keys_proc = ->(hash) { hash.sort.to_h } | ||
| if defined?(::Ractor) && Ractor.respond_to?(:shareable_lambda) | ||
| sort_keys_proc = Ractor.shareable_lambda(&sort_keys_proc) | ||
| end | ||
| generator::State.default_sort_keys_proc = sort_keys_proc | ||
| @generator = generator | ||
@@ -160,0 +169,0 @@ if generator.const_defined?(:GeneratorMethods) |
+26
-0
@@ -44,3 +44,29 @@ # frozen_string_literal: true | ||
| if defined?(ResumableParser) # Not yet available on JRuby | ||
| class ResumableParser | ||
| # Returns whether the parser is entirely done: no unconsumed bytes in | ||
| # the buffer, no document under construction and no parsed value | ||
| # awaiting retrieval. | ||
| # | ||
| # The main use case is detecting a truncated stream once the input is | ||
| # exhausted: | ||
| # | ||
| # loop do | ||
| # begin | ||
| # parser << socket.readpartial(4096) | ||
| # rescue EOFError | ||
| # break | ||
| # end | ||
| # while parser.parse | ||
| # process(parser.value) | ||
| # end | ||
| # end | ||
| # warn "stream was truncated" unless parser.empty? | ||
| def empty? | ||
| eos? && !partial_value? && !value? | ||
| end | ||
| end | ||
| end | ||
| JSON_LOADED = true unless defined?(JSON::JSON_LOADED) | ||
| end |
@@ -57,2 +57,3 @@ # frozen_string_literal: true | ||
| buffer_initial_length: buffer_initial_length, | ||
| sort_keys: sort_keys | ||
| } | ||
@@ -59,0 +60,0 @@ |
@@ -114,2 +114,4 @@ # frozen_string_literal: true | ||
| class State | ||
| singleton_class.attr_accessor :default_sort_keys_proc # :nodoc: | ||
| def self.generate(obj, opts = nil, io = nil) | ||
@@ -168,2 +170,3 @@ new(opts).generate(obj, io) | ||
| @max_nesting = 100 | ||
| @sort_keys = false | ||
| configure(opts) if opts | ||
@@ -204,2 +207,29 @@ end | ||
| # Controls key sorting in the generated JSON. If set to +true+, object | ||
| # keys are sorted by key lexicographically. If set to a Proc, it | ||
| # receives the entire Hash and must return a Hash with its pairs in the | ||
| # desired order. | ||
| attr_reader :sort_keys | ||
| def sort_keys=(value) # :nodoc: | ||
| type_error = false | ||
| @sort_keys = case value | ||
| when Proc | ||
| value | ||
| when true | ||
| State.default_sort_keys_proc | ||
| when nil, false | ||
| false | ||
| else | ||
| type_error = true | ||
| false | ||
| end | ||
| if type_error | ||
| raise TypeError, "The `sort_keys` argument must be a boolean or a Proc" | ||
| end | ||
| @sort_keys | ||
| end | ||
| # :stopdoc: | ||
@@ -291,2 +321,3 @@ attr_reader :buffer_initial_length | ||
| @ascii_only = opts[:ascii_only] if opts.key?(:ascii_only) | ||
| self.sort_keys = opts[:sort_keys] if opts.key?(:sort_keys) | ||
| @depth = opts[:depth] || 0 | ||
@@ -356,5 +387,9 @@ @buffer_initial_length ||= opts[:buffer_initial_length] | ||
| if @indent.empty? and @space.empty? and @space_before.empty? and @object_nl.empty? and @array_nl.empty? and | ||
| !@ascii_only and !@script_safe and @max_nesting == 0 and (!@strict || Symbol === obj) | ||
| !@ascii_only and !@script_safe and @max_nesting == 0 and (!@strict || Symbol === obj) and !@sort_keys | ||
| result = generate_json(obj, ''.dup) | ||
| else | ||
| if @sort_keys | ||
| obj = @sort_keys.call(obj) | ||
| end | ||
| result = obj.to_json(self) | ||
@@ -361,0 +396,0 @@ end |
| # frozen_string_literal: true | ||
| module JSON | ||
| VERSION = '2.20.0' | ||
| VERSION = '2.21.0' | ||
| end |
+5
-5
@@ -88,3 +88,3 @@ # JSON implementation for Ruby | ||
| JSON.generate(Object.new, strict: true) # => Object not allowed in JSON (JSON::GeneratorError) | ||
| JSON.generate(Position.new(1, 2)) # => Position not allowed in JSON (JSON::GeneratorError) | ||
| JSON.generate(Position.new(1, 2), strict: true) # => Position not allowed in JSON (JSON::GeneratorError) | ||
| ``` | ||
@@ -121,9 +121,9 @@ | ||
| ```ruby | ||
| coder = JSON::Combining.new do |object, is_object_key| | ||
| coder = JSON::Coder.new do |object, is_object_key| | ||
| case object | ||
| when String | ||
| if !string.valid_encoding? || string.encoding != Encoding::UTF_8 | ||
| Base64.encode64(string) | ||
| if !object.valid_encoding? || object.encoding != Encoding::UTF_8 | ||
| Base64.encode64(object) | ||
| else | ||
| string | ||
| object | ||
| end | ||
@@ -130,0 +130,0 @@ else |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display