json 2.7.2-java → 2.7.3.rc1-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md ADDED
@@ -0,0 +1,264 @@
1
+ # JSON implementation for Ruby
2
+
3
+ [![CI](https://github.com/ruby/json/actions/workflows/ci.yml/badge.svg)](https://github.com/ruby/json/actions/workflows/ci.yml)
4
+
5
+ ## Description
6
+
7
+ This is an implementation of the JSON specification according to RFC 7159
8
+ http://www.ietf.org/rfc/rfc7159.txt . There is two variants available:
9
+
10
+ * A pure ruby variant, that relies on the `strscan` extensions, which is
11
+ part of the ruby standard library.
12
+ * The quite a bit faster native extension variant, which is in parts
13
+ implemented in C or Java and comes with a parser generated by the [Ragel]
14
+ state machine compiler.
15
+
16
+ Both variants of the JSON generator generate UTF-8 character sequences by
17
+ default. If an :ascii\_only option with a true value is given, they escape all
18
+ non-ASCII and control characters with \uXXXX escape sequences, and support
19
+ UTF-16 surrogate pairs in order to be able to generate the whole range of
20
+ unicode code points.
21
+
22
+ All strings, that are to be encoded as JSON strings, should be UTF-8 byte
23
+ sequences on the Ruby side. To encode raw binary strings, that aren't UTF-8
24
+ encoded, please use the to\_json\_raw\_object method of String (which produces
25
+ an object, that contains a byte array) and decode the result on the receiving
26
+ endpoint.
27
+
28
+ ## Installation
29
+
30
+ It's recommended to use the extension variant of JSON, because it's faster than
31
+ the pure ruby variant. If you cannot build it on your system, you can settle
32
+ for the latter.
33
+
34
+ Install the gem and add to the application's Gemfile by executing:
35
+
36
+ $ bundle add json
37
+
38
+ If bundler is not being used to manage dependencies, install the gem by executing:
39
+
40
+ $ gem install json
41
+
42
+
43
+ There is also a pure ruby json only variant of the gem, that can be installed
44
+ with:
45
+
46
+ $ gem install json_pure
47
+
48
+ ## Usage
49
+
50
+ To use JSON you can
51
+
52
+ ```ruby
53
+ require 'json'
54
+ ```
55
+
56
+ to load the installed variant (either the extension `'json'` or the pure
57
+ variant `'json_pure'`). If you have installed the extension variant, you can
58
+ pick either the extension variant or the pure variant by typing
59
+
60
+ ```ruby
61
+ require 'json/ext'
62
+ ```
63
+
64
+ or
65
+
66
+ ```ruby
67
+ require 'json/pure'
68
+ ```
69
+
70
+ Now you can parse a JSON document into a ruby data structure by calling
71
+
72
+ ```ruby
73
+ JSON.parse(document)
74
+ ```
75
+
76
+ If you want to generate a JSON document from a ruby data structure call
77
+ ```ruby
78
+ JSON.generate(data)
79
+ ```
80
+
81
+ You can also use the `pretty_generate` method (which formats the output more
82
+ verbosely and nicely) or `fast_generate` (which doesn't do any of the security
83
+ checks generate performs, e. g. nesting deepness checks).
84
+
85
+ There are also the JSON and JSON[] methods which use parse on a String or
86
+ generate a JSON document from an array or hash:
87
+
88
+ ```ruby
89
+ document = JSON 'test' => 23 # => "{\"test\":23}"
90
+ document = JSON['test' => 23] # => "{\"test\":23}"
91
+ ```
92
+
93
+ and
94
+
95
+ ```ruby
96
+ data = JSON '{"test":23}' # => {"test"=>23}
97
+ data = JSON['{"test":23}'] # => {"test"=>23}
98
+ ```
99
+
100
+ You can choose to load a set of common additions to ruby core's objects if
101
+ you
102
+
103
+ ```ruby
104
+ require 'json/add/core'
105
+ ```
106
+
107
+ After requiring this you can, e. g., serialise/deserialise Ruby ranges:
108
+
109
+ ```ruby
110
+ JSON JSON(1..10) # => 1..10
111
+ ```
112
+
113
+ To find out how to add JSON support to other or your own classes, read the
114
+ section "More Examples" below.
115
+
116
+ ## Serializing exceptions
117
+
118
+ The JSON module doesn't extend `Exception` by default. If you convert an `Exception`
119
+ object to JSON, it will by default only include the exception message.
120
+
121
+ To include the full details, you must either load the `json/add/core` mentioned
122
+ above, or specifically load the exception addition:
123
+
124
+ ```ruby
125
+ require 'json/add/exception'
126
+ ```
127
+
128
+ ## More Examples
129
+
130
+ To create a JSON document from a ruby data structure, you can call
131
+ `JSON.generate` like that:
132
+
133
+ ```ruby
134
+ json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
135
+ # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
136
+ ```
137
+
138
+ To get back a ruby data structure from a JSON document, you have to call
139
+ JSON.parse on it:
140
+
141
+ ```ruby
142
+ JSON.parse json
143
+ # => [1, 2, {"a"=>3.141}, false, true, nil, "4..10"]
144
+ ```
145
+
146
+ Note, that the range from the original data structure is a simple
147
+ string now. The reason for this is, that JSON doesn't support ranges
148
+ or arbitrary classes. In this case the json library falls back to call
149
+ `Object#to_json`, which is the same as `#to_s.to_json`.
150
+
151
+ It's possible to add JSON support serialization to arbitrary classes by
152
+ simply implementing a more specialized version of the `#to_json method`, that
153
+ should return a JSON object (a hash converted to JSON with `#to_json`) like
154
+ this (don't forget the `*a` for all the arguments):
155
+
156
+ ```ruby
157
+ class Range
158
+ def to_json(*a)
159
+ {
160
+ 'json_class' => self.class.name, # = 'Range'
161
+ 'data' => [ first, last, exclude_end? ]
162
+ }.to_json(*a)
163
+ end
164
+ end
165
+ ```
166
+
167
+ The hash key `json_class` is the class, that will be asked to deserialise the
168
+ JSON representation later. In this case it's `Range`, but any namespace of
169
+ the form `A::B` or `::A::B` will do. All other keys are arbitrary and can be
170
+ used to store the necessary data to configure the object to be deserialised.
171
+
172
+ If the key `json_class` is found in a JSON object, the JSON parser checks
173
+ if the given class responds to the `json_create` class method. If so, it is
174
+ called with the JSON object converted to a Ruby hash. So a range can
175
+ be deserialised by implementing `Range.json_create` like this:
176
+
177
+ ```ruby
178
+ class Range
179
+ def self.json_create(o)
180
+ new(*o['data'])
181
+ end
182
+ end
183
+ ```
184
+
185
+ Now it possible to serialise/deserialise ranges as well:
186
+
187
+ ```ruby
188
+ json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
189
+ # => "[1,2,{\"a\":3.141},false,true,null,{\"json_class\":\"Range\",\"data\":[4,10,false]}]"
190
+ JSON.parse json
191
+ # => [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
192
+ json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
193
+ # => "[1,2,{\"a\":3.141},false,true,null,{\"json_class\":\"Range\",\"data\":[4,10,false]}]"
194
+ JSON.parse json, :create_additions => true
195
+ # => [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
196
+ ```
197
+
198
+ `JSON.generate` always creates the shortest possible string representation of a
199
+ ruby data structure in one line. This is good for data storage or network
200
+ protocols, but not so good for humans to read. Fortunately there's also
201
+ `JSON.pretty_generate` (or `JSON.pretty_generate`) that creates a more readable
202
+ output:
203
+
204
+ ```ruby
205
+ puts JSON.pretty_generate([1, 2, {"a"=>3.141}, false, true, nil, 4..10])
206
+ [
207
+ 1,
208
+ 2,
209
+ {
210
+ "a": 3.141
211
+ },
212
+ false,
213
+ true,
214
+ null,
215
+ {
216
+ "json_class": "Range",
217
+ "data": [
218
+ 4,
219
+ 10,
220
+ false
221
+ ]
222
+ }
223
+ ]
224
+ ```
225
+
226
+ There are also the methods `Kernel#j` for generate, and `Kernel#jj` for
227
+ `pretty_generate` output to the console, that work analogous to Core Ruby's `p` and
228
+ the `pp` library's `pp` methods.
229
+
230
+ ## Development
231
+
232
+ ### Release
233
+
234
+ Update the `lib/json/version.rb` file.
235
+
236
+ ```
237
+ rbenv shell 2.6.5
238
+ rake build
239
+ gem push pkg/json-2.3.0.gem
240
+
241
+ rbenv shell jruby-9.2.9.0
242
+ rake build
243
+ gem push pkg/json-2.3.0-java.gem
244
+ ```
245
+
246
+ ## Author
247
+
248
+ Florian Frank <mailto:flori@ping.de>
249
+
250
+ ## License
251
+
252
+ Ruby License, see https://www.ruby-lang.org/en/about/license.txt.
253
+
254
+ ## Download
255
+
256
+ The latest version of this library can be downloaded at
257
+
258
+ * https://rubygems.org/gems/json
259
+
260
+ Online Documentation should be located at
261
+
262
+ * https://www.rubydoc.info/gems/json
263
+
264
+ [Ragel]: http://www.colm.net/open-source/ragel/
data/json.gemspec ADDED
@@ -0,0 +1,61 @@
1
+ version = File.foreach(File.join(__dir__, "lib/json/version.rb")) do |line|
2
+ /^\s*VERSION\s*=\s*'(.*)'/ =~ line and break $1
3
+ end rescue nil
4
+
5
+ spec = Gem::Specification.new do |s|
6
+ java_ext = Gem::Platform === s.platform && s.platform =~ 'java' || RUBY_ENGINE == 'jruby'
7
+
8
+ s.name = "json"
9
+ s.version = version
10
+
11
+ s.summary = "JSON Implementation for Ruby"
12
+ s.homepage = "https://ruby.github.io/json"
13
+ s.metadata = {
14
+ 'bug_tracker_uri' => 'https://github.com/ruby/json/issues',
15
+ 'changelog_uri' => 'https://github.com/ruby/json/blob/master/CHANGES.md',
16
+ 'documentation_uri' => 'https://ruby.github.io/json/doc/index.html',
17
+ 'homepage_uri' => s.homepage,
18
+ 'source_code_uri' => 'https://github.com/ruby/json',
19
+ 'wiki_uri' => 'https://github.com/ruby/json/wiki'
20
+ }
21
+
22
+ s.required_ruby_version = Gem::Requirement.new(">= 2.3")
23
+
24
+ if java_ext
25
+ s.description = "A JSON implementation as a JRuby extension."
26
+ s.author = "Daniel Luz"
27
+ s.email = "dev+ruby@mernen.com"
28
+ else
29
+ s.description = "This is a JSON implementation as a Ruby extension in C."
30
+ s.authors = ["Florian Frank"]
31
+ s.email = "flori@ping.de"
32
+ end
33
+
34
+ s.licenses = ["Ruby"]
35
+
36
+ s.extra_rdoc_files = ["README.md"]
37
+ s.rdoc_options = ["--title", "JSON implementation for Ruby", "--main", "README.md"]
38
+
39
+ s.files = [
40
+ "CHANGES.md",
41
+ "COPYING",
42
+ "BSDL",
43
+ "LEGAL",
44
+ "README.md",
45
+ "json.gemspec",
46
+ *Dir["lib/**/*.rb"],
47
+ ]
48
+
49
+ if java_ext
50
+ s.platform = 'java'
51
+ else
52
+ s.extensions = Dir["ext/json/**/extconf.rb"]
53
+ s.files += Dir["ext/json/**/*.{c,h,rl}"]
54
+ end
55
+ end
56
+
57
+ if RUBY_ENGINE == 'jruby' && $0 == __FILE__
58
+ Gem::Builder.new(spec).build
59
+ else
60
+ spec
61
+ end
@@ -1,4 +1,4 @@
1
- #frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
3
  require 'json'
4
4
  end
@@ -1,4 +1,4 @@
1
- #frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
3
  require 'json'
4
4
  end
data/lib/json/add/core.rb CHANGED
@@ -1,4 +1,4 @@
1
- #frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  # This file requires the implementations of ruby core's custom objects for
3
3
  # serialisation/deserialisation.
4
4
 
data/lib/json/add/date.rb CHANGED
@@ -1,4 +1,4 @@
1
- #frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
3
  require 'json'
4
4
  end
@@ -1,4 +1,4 @@
1
- #frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
3
  require 'json'
4
4
  end
@@ -1,4 +1,4 @@
1
- #frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
3
  require 'json'
4
4
  end
@@ -1,4 +1,4 @@
1
- #frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
3
  require 'json'
4
4
  end
@@ -1,4 +1,4 @@
1
- #frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
3
  require 'json'
4
4
  end
@@ -1,4 +1,4 @@
1
- #frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
3
  require 'json'
4
4
  end
@@ -1,4 +1,4 @@
1
- #frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
3
  require 'json'
4
4
  end
@@ -1,4 +1,4 @@
1
- #frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
3
  require 'json'
4
4
  end
@@ -1,5 +1,4 @@
1
-
2
- #frozen_string_literal: false
1
+ # frozen_string_literal: true
3
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
4
3
  require 'json'
5
4
  end
data/lib/json/add/time.rb CHANGED
@@ -1,4 +1,4 @@
1
- #frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
3
  require 'json'
4
4
  end
@@ -10,11 +10,7 @@ class Time
10
10
  if usec = object.delete('u') # used to be tv_usec -> tv_nsec
11
11
  object['n'] = usec * 1000
12
12
  end
13
- if method_defined?(:tv_nsec)
14
- at(object['s'], Rational(object['n'], 1000))
15
- else
16
- at(object['s'], object['n'] / 1000)
17
- end
13
+ at(object['s'], Rational(object['n'], 1000))
18
14
  end
19
15
 
20
16
  # Methods <tt>Time#as_json</tt> and +Time.json_create+ may be used
@@ -34,13 +30,10 @@ class Time
34
30
  # # => 2023-11-25 11:00:56.472846644 -0600
35
31
  #
36
32
  def as_json(*)
37
- nanoseconds = [ tv_usec * 1000 ]
38
- respond_to?(:tv_nsec) and nanoseconds << tv_nsec
39
- nanoseconds = nanoseconds.max
40
33
  {
41
34
  JSON.create_id => self.class.name,
42
35
  's' => tv_sec,
43
- 'n' => nanoseconds,
36
+ 'n' => tv_nsec,
44
37
  }
45
38
  end
46
39
 
data/lib/json/common.rb CHANGED
@@ -1,4 +1,4 @@
1
- #frozen_string_literal: false
1
+ #frozen_string_literal: true
2
2
  require 'json/version'
3
3
 
4
4
  module JSON
@@ -20,11 +20,16 @@ module JSON
20
20
  # ruby = [0, 1, nil]
21
21
  # JSON[ruby] # => '[0,1,null]'
22
22
  def [](object, opts = {})
23
- if object.respond_to? :to_str
24
- JSON.parse(object.to_str, opts)
25
- else
26
- JSON.generate(object, opts)
23
+ if object.is_a?(String)
24
+ return JSON.parse(object, opts)
25
+ elsif object.respond_to?(:to_str)
26
+ str = object.to_str
27
+ if str.is_a?(String)
28
+ return JSON.parse(object.to_str, opts)
29
+ end
27
30
  end
31
+
32
+ JSON.generate(object, opts)
28
33
  end
29
34
 
30
35
  # Returns the JSON parser class that is used by JSON. This is either
@@ -112,23 +117,17 @@ module JSON
112
117
  attr_accessor :state
113
118
  end
114
119
 
115
- DEFAULT_CREATE_ID = 'json_class'.freeze
116
- private_constant :DEFAULT_CREATE_ID
117
-
118
- CREATE_ID_TLS_KEY = "JSON.create_id".freeze
119
- private_constant :CREATE_ID_TLS_KEY
120
-
121
120
  # Sets create identifier, which is used to decide if the _json_create_
122
121
  # hook of a class should be called; initial value is +json_class+:
123
122
  # JSON.create_id # => 'json_class'
124
123
  def self.create_id=(new_value)
125
- Thread.current[CREATE_ID_TLS_KEY] = new_value.dup.freeze
124
+ Thread.current[:"JSON.create_id"] = new_value.dup.freeze
126
125
  end
127
126
 
128
127
  # Returns the current create identifier.
129
128
  # See also JSON.create_id=.
130
129
  def self.create_id
131
- Thread.current[CREATE_ID_TLS_KEY] || DEFAULT_CREATE_ID
130
+ Thread.current[:"JSON.create_id"] || 'json_class'
132
131
  end
133
132
 
134
133
  NaN = 0.0/0
@@ -216,8 +215,12 @@ module JSON
216
215
  # # Raises JSON::ParserError (783: unexpected token at ''):
217
216
  # JSON.parse('')
218
217
  #
219
- def parse(source, opts = {})
220
- Parser.new(source, **(opts||{})).parse
218
+ def parse(source, opts = nil)
219
+ if opts.nil?
220
+ Parser.new(source).parse
221
+ else
222
+ Parser.new(source, opts).parse
223
+ end
221
224
  end
222
225
 
223
226
  # :call-seq:
@@ -406,7 +409,7 @@ module JSON
406
409
  self.load_default_options = {
407
410
  :max_nesting => false,
408
411
  :allow_nan => true,
409
- :allow_blank => true,
412
+ :allow_blank => true,
410
413
  :create_additions => true,
411
414
  }
412
415
 
@@ -538,15 +541,23 @@ module JSON
538
541
  # #<Admin:0x00000000064c41f8
539
542
  # @attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
540
543
  #
541
- def load(source, proc = nil, options = {})
542
- opts = load_default_options.merge options
543
- if source.respond_to? :to_str
544
- source = source.to_str
545
- elsif source.respond_to? :to_io
546
- source = source.to_io.read
547
- elsif source.respond_to?(:read)
548
- source = source.read
544
+ def load(source, proc = nil, options = nil)
545
+ opts = if options.nil?
546
+ load_default_options
547
+ else
548
+ load_default_options.merge(options)
549
+ end
550
+
551
+ unless source.is_a?(String)
552
+ if source.respond_to? :to_str
553
+ source = source.to_str
554
+ elsif source.respond_to? :to_io
555
+ source = source.to_io.read
556
+ elsif source.respond_to?(:read)
557
+ source = source.read
558
+ end
549
559
  end
560
+
550
561
  if opts[:allow_blank] && (source.nil? || source.empty?)
551
562
  source = 'null'
552
563
  end
@@ -576,13 +587,12 @@ module JSON
576
587
  # Sets or returns the default options for the JSON.dump method.
577
588
  # Initially:
578
589
  # opts = JSON.dump_default_options
579
- # opts # => {:max_nesting=>false, :allow_nan=>true, :script_safe=>false}
590
+ # opts # => {:max_nesting=>false, :allow_nan=>true}
580
591
  attr_accessor :dump_default_options
581
592
  end
582
593
  self.dump_default_options = {
583
594
  :max_nesting => false,
584
595
  :allow_nan => true,
585
- :script_safe => false,
586
596
  }
587
597
 
588
598
  # :call-seq:
@@ -613,26 +623,42 @@ module JSON
613
623
  # Output:
614
624
  # {"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}
615
625
  def dump(obj, anIO = nil, limit = nil, kwargs = nil)
616
- io_limit_opt = [anIO, limit, kwargs].compact
617
- kwargs = io_limit_opt.pop if io_limit_opt.last.is_a?(Hash)
618
- anIO, limit = io_limit_opt
619
- if anIO.respond_to?(:to_io)
620
- anIO = anIO.to_io
621
- elsif limit.nil? && !anIO.respond_to?(:write)
622
- anIO, limit = nil, anIO
626
+ if kwargs.nil?
627
+ if limit.nil?
628
+ if anIO.is_a?(Hash)
629
+ kwargs = anIO
630
+ anIO = nil
631
+ end
632
+ elsif limit.is_a?(Hash)
633
+ kwargs = limit
634
+ limit = nil
635
+ end
623
636
  end
637
+
638
+ unless anIO.nil?
639
+ if anIO.respond_to?(:to_io)
640
+ anIO = anIO.to_io
641
+ elsif limit.nil? && !anIO.respond_to?(:write)
642
+ anIO, limit = nil, anIO
643
+ end
644
+ end
645
+
624
646
  opts = JSON.dump_default_options
625
647
  opts = opts.merge(:max_nesting => limit) if limit
626
648
  opts = merge_dump_options(opts, **kwargs) if kwargs
627
- result = generate(obj, opts)
628
- if anIO
649
+
650
+ result = begin
651
+ generate(obj, opts)
652
+ rescue JSON::NestingError
653
+ raise ArgumentError, "exceed depth limit"
654
+ end
655
+
656
+ if anIO.nil?
657
+ result
658
+ else
629
659
  anIO.write result
630
660
  anIO
631
- else
632
- result
633
661
  end
634
- rescue JSON::NestingError
635
- raise ArgumentError, "exceed depth limit"
636
662
  end
637
663
 
638
664
  # Encodes string using String.encode.
@@ -678,11 +704,16 @@ module ::Kernel
678
704
  # The _opts_ argument is passed through to generate/parse respectively. See
679
705
  # generate and parse for their documentation.
680
706
  def JSON(object, *args)
681
- if object.respond_to? :to_str
682
- JSON.parse(object.to_str, args.first)
683
- else
684
- JSON.generate(object, args.first)
707
+ if object.is_a?(String)
708
+ return JSON.parse(object, args.first)
709
+ elsif object.respond_to?(:to_str)
710
+ str = object.to_str
711
+ if str.is_a?(String)
712
+ return JSON.parse(object.to_str, args.first)
713
+ end
685
714
  end
715
+
716
+ JSON.generate(object, args.first)
686
717
  end
687
718
  end
688
719