json 2.7.2-java → 2.7.3.rc1-java

Sign up to get free protection for your applications and to get access to all the features.
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