oj 3.13.9 → 3.13.12

Sign up to get free protection for your applications and to get access to all the features.
data/lib/oj/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '3.13.9'
4
+ VERSION = '3.13.12'
5
5
  end
data/pages/JsonGem.md CHANGED
@@ -1,3 +1,18 @@
1
+ # JSON Quickstart
2
+
3
+ To have Oj universally "take over" many methods on the JSON constant (`load`, `parse`, etc.) with
4
+ their faster Oj counterparts, in a mode that is compatible with the json gem:
5
+
6
+ ```ruby
7
+ Oj.mimic_JSON()
8
+ ```
9
+
10
+ If the project does not already use the json gem, `JSON` will become available.
11
+ If the project does require the json gem, `Oj.mimic_JSON()` should be invoked after the
12
+ json gem has been required.
13
+
14
+ For more details and options, read on...
15
+
1
16
  # Oj JSON Gem Compatibility
2
17
 
3
18
  The `:compat` mode mimics the json gem. The json gem is built around the use
data/pages/Modes.md CHANGED
@@ -39,7 +39,8 @@ if a non-native type is encountered instead of raising an Exception.
39
39
  The `:compat` mode mimics the json gem. The json gem is built around the use
40
40
  of the `to_json(*)` method defined for a class. Oj attempts to provide the
41
41
  same functionality by being a drop in replacement with a few
42
- exceptions. [{file:JsonGem.md}](JsonGem.md) includes more details on
42
+ exceptions. To universally replace many `JSON` methods with their faster Oj counterparts,
43
+ simply run `Oj.mimic_json`. [{file:JsonGem.md}](JsonGem.md) includes more details on
43
44
  compatibility and use.
44
45
 
45
46
  ## :rails Mode
@@ -108,11 +109,11 @@ information.
108
109
  | :float_precision | Fixnum | x | x | | | | x | |
109
110
  | :hash_class | Class | | | x | x | | x | |
110
111
  | :ignore | Array | | | | | x | x | |
111
- | :indent | Integer | x | x | 3 | 4 | x | x | x |
112
+ | :indent | Integer | x | x | 4 | 4 | x | x | x |
112
113
  | :indent_str | String | | | x | x | | x | |
113
114
  | :integer_range | Range | x | x | x | x | x | x | x |
114
115
  | :match_string | Hash | | | x | x | | x | |
115
- | :max_nesting | Fixnum | 4 | 4 | x | | 5 | 4 | |
116
+ | :max_nesting | Fixnum | 5 | 5 | x | | 5 | 5 | |
116
117
  | :mode | Symbol | - | - | - | - | - | - | |
117
118
  | :nan | Symbol | | | | | | x | |
118
119
  | :nilnil | Boolean | | | | | | x | |
@@ -140,6 +141,8 @@ information.
140
141
  3. By default the bigdecimal_as decimal is not set and the default encoding
141
142
  for Rails is as a string. Setting the value to true will encode a
142
143
  BigDecimal as a number which breaks compatibility.
144
+ Note: after version 3.11.3 both `Oj.generate` and `JSON.generate`
145
+ will not honour this option in Rails Mode, detais on https://github.com/ohler55/oj/pull/716.
143
146
 
144
147
  4. The integer indent value in the default options will be honored by since
145
148
  the json gem expects a String type the indent in calls to 'to_json()',
data/pages/Rails.md CHANGED
@@ -1,3 +1,15 @@
1
+ # Rails Quickstart
2
+
3
+ To universally replace Rails' use of the json gem with Oj, and also
4
+ have Oj "take over" many methods on the JSON constant (`load`, `parse`, etc.) with
5
+ their faster Oj counterparts, add this to an initializer:
6
+
7
+ ```ruby
8
+ Oj.optimize_rails()
9
+ ```
10
+
11
+ For more details and options, read on...
12
+
1
13
  # Oj Rails Compatibility
2
14
 
3
15
  The `:rails` mode mimics the ActiveSupport version 5 encoder. Rails and
data/test/bar.rb CHANGED
@@ -6,11 +6,4 @@ $: << File.join(File.dirname(__FILE__), "../ext")
6
6
 
7
7
  require 'oj'
8
8
 
9
- json = %|[{"x12345678901234567890": true}]|
10
-
11
- p = Oj::Parser.new(:usual)
12
- p.cache_keys = false
13
- p.symbol_keys = true
14
- x = p.parse(json)
15
-
16
- pp x
9
+ Oj.load(%|{"time":"2021-08-16 12:12:15","a":"5","b":"5"|)
data/test/foo.rb CHANGED
@@ -4,17 +4,74 @@ $: << '.'
4
4
  $: << File.join(File.dirname(__FILE__), "../lib")
5
5
  $: << File.join(File.dirname(__FILE__), "../ext")
6
6
 
7
- # require 'json'
8
- require 'oj'
9
- Oj.mimic_JSON
7
+ require "oj"
8
+ require "socket"
9
+ require 'io/nonblock'
10
10
 
11
- source = %( {"a": 1, "b": 2} )
12
- puts "JSON.load, no symbolize => OK"
13
- pp JSON.load( source )
14
- puts "JSON.load, do symbolize => KO: keys are not symbols"
15
- #pp JSON.load( source, nil, symbolize_names: true, create_additions: false )
16
- pp JSON.load( source, nil, symbolize_names: true, create_additions: false )
17
- puts "JSON.parse, no symbolize => OK"
18
- pp JSON.parse( source )
19
- puts "JSON.parse, do symbolize => OK"
20
- pp JSON.parse( source, symbolize_names: true )
11
+ #pid = spawn("nc -d 0.1 -l 5000", out: "/dev/null")
12
+ pid = spawn("nc -i 1 -l 7777", out: "/dev/null")
13
+ at_exit { Process.kill 9, pid }
14
+ sleep 0.2
15
+ s = Socket.tcp("localhost", 7777)
16
+ s.nonblock = false
17
+ 1_000_000.times do |x|
18
+ Oj.to_stream(s, { x: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]})
19
+ end
20
+
21
+ =begin
22
+ IO.pipe do |r, w|
23
+ if fork
24
+ r.close
25
+ #w.nonblock = false
26
+ 1_000_000.times do |i|
27
+ begin
28
+ Oj.to_stream(w, { x: i})
29
+ rescue IOError => e
30
+ puts "*** #{i} raised #{e.class}: #{e}"
31
+ IO.select(nil, [w])
32
+ retry
33
+ end
34
+ w.puts
35
+ end
36
+ else
37
+ w.close
38
+ sleep(0.1)
39
+ r.each_line { |b|
40
+ #print b
41
+ }
42
+ r.close
43
+ Process.exit(0)
44
+ end
45
+ end
46
+ =end
47
+
48
+ =begin
49
+ IO.pipe do |r, w|
50
+ if fork
51
+ r.close
52
+ #w.nonblock = false
53
+ a = []
54
+ 10_000.times do |i|
55
+ a << i
56
+ end
57
+ begin
58
+ Oj.to_stream(w, a, indent: 2)
59
+ rescue IOError => e
60
+ puts "*** raised #{e.class}: #{e}"
61
+ puts "*** fileno: #{w.fileno}"
62
+ puts "*** is an IO?: #{w.kind_of?(IO)}"
63
+ IO.select(nil, [w])
64
+ retry
65
+ end
66
+ w.puts
67
+ else
68
+ w.close
69
+ sleep(0.5)
70
+ r.each_line { |b|
71
+ #print b
72
+ }
73
+ r.close
74
+ Process.exit(0)
75
+ end
76
+ end
77
+ =end
data/test/perf_dump.rb ADDED
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ $: << '.'
5
+ $: << File.join(File.dirname(__FILE__), "../lib")
6
+ $: << File.join(File.dirname(__FILE__), "../ext")
7
+
8
+ require 'optparse'
9
+ require 'oj'
10
+
11
+ $verbose = false
12
+ $indent = 2
13
+ $iter = 100_000
14
+ $size = 2
15
+
16
+ opts = OptionParser.new
17
+ opts.on("-v", "verbose") { $verbose = true }
18
+ opts.on("-c", "--count [Int]", Integer, "iterations") { |i| $iter = i }
19
+ opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
20
+ opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") { |i| $size = i }
21
+ opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
22
+ files = opts.parse(ARGV)
23
+
24
+ $obj = {
25
+ 'a' => 'Alpha', # string
26
+ 'b' => true, # boolean
27
+ 'c' => 12345, # number
28
+ 'd' => [ true, [false, [-123456789, nil], 3.9676, ['Something else.', false], nil]], # mix it up array
29
+ 'e' => { 'zero' => nil, 'one' => 1, 'two' => 2, 'three' => [3], 'four' => [0, 1, 2, 3, 4] }, # hash
30
+ 'f' => nil, # nil
31
+ 'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
32
+ 'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
33
+ }
34
+
35
+ Oj.default_options = { :indent => $indent, :mode => :strict }
36
+
37
+ if 0 < $size
38
+ o = $obj
39
+ $obj = []
40
+ (4 * $size).times do
41
+ $obj << o
42
+ end
43
+ end
44
+
45
+ $json = Oj.dump($obj)
46
+ GC.start
47
+ start = Time.now
48
+ $iter.times { Oj.dump($obj) }
49
+ duration = Time.now - start
50
+ puts "Dumped #{$json.length} byte JSON #{$iter} times in %0.3f seconds or %0.3f iteration/sec." % [duration, $iter / duration]
data/test/test_fast.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # coding: utf-8
2
3
  # frozen_string_literal: true
3
4
 
4
5
  $: << File.dirname(__FILE__)
@@ -395,6 +396,19 @@ class DocTest < Minitest::Test
395
396
  end
396
397
  end
397
398
 
399
+ def test_nested_each_child
400
+ h = {}
401
+ Oj::Doc.open('{"a":1,"c":[2],"d":3}') do |doc|
402
+ doc.each_child('/') do |child|
403
+ h[child.path] = child.fetch
404
+ child.each_child do |grandchild|
405
+ h[grandchild.path] = grandchild.fetch
406
+ end
407
+ end
408
+ end
409
+ assert_equal({"/a"=>1, "/c"=>[2], "/c/1"=>2, "/d"=>3}, h)
410
+ end
411
+
398
412
  def test_size
399
413
  Oj::Doc.open('[1,2,3]') do |doc|
400
414
  assert_equal(4, doc.size)
@@ -491,6 +505,11 @@ class DocTest < Minitest::Test
491
505
  assert_equal({'/a/x' => 2, '/b/y' => 4}, results)
492
506
  end
493
507
 
508
+ def test_doc_empty
509
+ result = Oj::Doc.open("") { |doc| doc.each_child {} }
510
+ assert_nil(result)
511
+ end
512
+
494
513
  def test_comment
495
514
  json = %{{
496
515
  "x"/*one*/:/*two*/true,//three
data/test/test_object.rb CHANGED
@@ -221,6 +221,13 @@ class ObjectJuice < Minitest::Test
221
221
 
222
222
  def teardown
223
223
  Oj.default_options = @default_options
224
+ #=begin
225
+ if '3.1.0' <= RUBY_VERSION && !(RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/)
226
+ #Oj::debug_odd("teardown before GC.verify_compaction_references")
227
+ GC.verify_compaction_references(double_heap: true, toward: :empty)
228
+ #Oj::debug_odd("teardown after GC.verify_compaction_references")
229
+ end
230
+ #=end
224
231
  end
225
232
 
226
233
  def test_nil
@@ -948,6 +955,11 @@ class ObjectJuice < Minitest::Test
948
955
 
949
956
  def test_odd_date
950
957
  dump_and_load(Date.new(2012, 6, 19), false)
958
+
959
+ Oj.register_odd(Date, Date, :jd, :jd)
960
+ json = Oj.dump(Date.new(2015, 3, 7), :mode => :object)
961
+ assert_equal(%|{"^O":"Date","jd":2457089}|, json)
962
+ dump_and_load(Date.new(2012, 6, 19), false)
951
963
  end
952
964
 
953
965
  def test_odd_datetime
@@ -972,13 +984,6 @@ class ObjectJuice < Minitest::Test
972
984
  dump_and_load(s, false)
973
985
  end
974
986
 
975
- def test_odd_date_replaced
976
- Oj.register_odd(Date, Date, :jd, :jd)
977
- json = Oj.dump(Date.new(2015, 3, 7), :mode => :object)
978
- assert_equal(%|{"^O":"Date","jd":2457089}|, json)
979
- dump_and_load(Date.new(2012, 6, 19), false)
980
- end
981
-
982
987
  def test_odd_raw
983
988
  Oj.register_odd_raw(Raw, Raw, :create, :to_json)
984
989
  json = Oj.dump(Raw.new(%|{"a":1}|), :mode => :object)
data/test/test_saj.rb CHANGED
@@ -180,7 +180,7 @@ class SajTest < Minitest::Test
180
180
  assert_equal([:add_value, 12345, nil], handler.calls.first)
181
181
  type, message, line, column = handler.calls.last
182
182
  assert_equal([:error, 1, 6], [type, line, column])
183
- assert_match(%r{invalid format, extra characters at line 1, column 6 \[(?:[a-z\.]+/)*saj\.c:\d+\]}, message)
183
+ assert_match(%r{invalid format, extra characters at line 1, column 6 \[(?:[A-Za-z]:\/)?(?:[a-z\.]+/)*saj\.c:\d+\]}, message)
184
184
  end
185
185
 
186
186
  end
data/test/test_various.rb CHANGED
@@ -528,7 +528,7 @@ class Juice < Minitest::Test
528
528
  assert_equal(58, obj.y)
529
529
  end
530
530
 
531
- # Stream Deeply Nested
531
+ # Stream Deeply Nested
532
532
  def test_deep_nest_dump
533
533
  begin
534
534
  a = []
@@ -541,7 +541,7 @@ class Juice < Minitest::Test
541
541
  assert(false, "*** expected an exception")
542
542
  end
543
543
 
544
- # Stream IO
544
+ # Stream IO
545
545
  def test_io_string
546
546
  src = { 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}
547
547
  output = StringIO.open("", "w+")
@@ -553,6 +553,9 @@ class Juice < Minitest::Test
553
553
  end
554
554
 
555
555
  def test_io_file
556
+ # Windows does not support fork
557
+ return if RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/
558
+
556
559
  src = { 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}
557
560
  filename = File.join(File.dirname(__FILE__), 'open_file_test.json')
558
561
  File.open(filename, "w") { |f|
@@ -564,6 +567,28 @@ class Juice < Minitest::Test
564
567
  assert_equal(src, obj)
565
568
  end
566
569
 
570
+ def test_io_stream
571
+ IO.pipe do |r, w|
572
+ if fork
573
+ r.close
574
+ #w.nonblock = false
575
+ a = []
576
+ 10_000.times do |i|
577
+ a << i
578
+ end
579
+ Oj.to_stream(w, a, indent: 2)
580
+ w.close
581
+ else
582
+ w.close
583
+ sleep(0.1) # to force a busy
584
+ cnt = 0
585
+ r.each_line { cnt += 1 }
586
+ r.close
587
+ Process.exit(0)
588
+ end
589
+ end
590
+ end
591
+
567
592
  # comments
568
593
  def test_comment_slash
569
594
  json = %{{
data/test/tests.rb CHANGED
@@ -18,7 +18,6 @@ require 'test_object'
18
18
  require 'test_saj'
19
19
  require 'test_scp'
20
20
  require 'test_strict'
21
- require 'test_various'
22
21
  require 'test_rails'
23
22
  require 'test_wab'
24
23
  require 'test_writer'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oj
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.13.9
4
+ version: 3.13.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-06 00:00:00.000000000 Z
11
+ date: 2022-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -117,6 +117,7 @@ files:
117
117
  - ext/oj/dump_object.c
118
118
  - ext/oj/dump_strict.c
119
119
  - ext/oj/encode.h
120
+ - ext/oj/encoder.c
120
121
  - ext/oj/err.c
121
122
  - ext/oj/err.h
122
123
  - ext/oj/extconf.rb
@@ -227,6 +228,7 @@ files:
227
228
  - test/mem.rb
228
229
  - test/perf.rb
229
230
  - test/perf_compat.rb
231
+ - test/perf_dump.rb
230
232
  - test/perf_fast.rb
231
233
  - test/perf_file.rb
232
234
  - test/perf_object.rb
@@ -306,7 +308,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
306
308
  - !ruby/object:Gem::Version
307
309
  version: '0'
308
310
  requirements: []
309
- rubygems_version: 3.2.22
311
+ rubygems_version: 3.3.3
310
312
  signing_key:
311
313
  specification_version: 4
312
314
  summary: A fast JSON parser and serializer.
@@ -359,6 +361,7 @@ test_files:
359
361
  - test/mem.rb
360
362
  - test/perf.rb
361
363
  - test/perf_compat.rb
364
+ - test/perf_dump.rb
362
365
  - test/perf_fast.rb
363
366
  - test/perf_file.rb
364
367
  - test/perf_object.rb