fast_multi_json 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/fast_multi_json.gemspec +1 -1
- data/lib/fast_multi_json/version.rb +1 -1
- data/lib/fast_multi_json.rb +105 -46
- data/scripts/perf_compat +271 -0
- metadata +11 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 529b67b9c69012bf49a7d98f885f1249cd513465beb91f41a7b39d588f4e806e
|
4
|
+
data.tar.gz: d38a9989290dfd0b111e686f27caf1d34eb7267e7777e95372a251b2d279d8df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ec9d5a43c50703ef7e801b9284340de4c5bbe55e99def2ae5c4ed9db6ba68acce7c7c7e43f76a1530d0ca4fd5da3dfa7067a0ca22b8106eac90d2f838435c07
|
7
|
+
data.tar.gz: 30a34ad18ffbb3eb7aca55eaa790633ce740d7e0cc2db485c3ca36c1994df90baf710403bfaaa75524fd50ac85bd3cd6cbe932e4fa3037cbd5dd9ee070925fd8
|
data/fast_multi_json.gemspec
CHANGED
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
31
31
|
spec.require_paths = ["lib"]
|
32
32
|
|
33
|
-
spec.add_development_dependency "bundler"
|
33
|
+
spec.add_development_dependency "bundler"
|
34
34
|
spec.add_development_dependency "rake", "~> 10.0"
|
35
35
|
spec.add_development_dependency "rspec", "~> 3.0"
|
36
36
|
end
|
data/lib/fast_multi_json.rb
CHANGED
@@ -1,45 +1,43 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fast_multi_json/version'
|
2
4
|
require 'logger'
|
3
5
|
|
4
6
|
# Usage:
|
5
7
|
# class Movie
|
6
8
|
# def to_json(payload)
|
7
|
-
# FastMultiJson.to_json(payload)
|
9
|
+
# ::FastMultiJson.to_json(payload)
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# def from_json(string)
|
13
|
+
# ::FastMultiJson.from_json(string)
|
8
14
|
# end
|
9
15
|
# end
|
10
16
|
module FastMultiJson
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
@value = yield
|
16
|
-
@error = nil
|
17
|
-
rescue LoadError => e
|
18
|
-
@error = e
|
19
|
-
end
|
20
|
-
|
21
|
-
def ok?
|
22
|
-
@error.nil?
|
23
|
-
end
|
17
|
+
def self.logger(logger=nil)
|
18
|
+
return @logger = logger if logger
|
19
|
+
@logger ||= Logger.new(IO::NULL)
|
20
|
+
end
|
24
21
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
22
|
+
def self.to_json(object)
|
23
|
+
_fast_to_json(object)
|
24
|
+
rescue NameError
|
25
|
+
define_to_json(::FastMultiJson)
|
26
|
+
_fast_to_json(object)
|
27
|
+
end
|
32
28
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
29
|
+
def self.from_json(string)
|
30
|
+
_fast_from_json(string)
|
31
|
+
rescue NameError
|
32
|
+
define_from_json(::FastMultiJson)
|
33
|
+
_fast_from_json(string)
|
37
34
|
end
|
38
|
-
private_constant :Result
|
39
35
|
|
40
|
-
def self.
|
41
|
-
|
42
|
-
|
36
|
+
def self.define_to_json(receiver)
|
37
|
+
cl = caller_locations[0]
|
38
|
+
method_body = to_json_method
|
39
|
+
logger.debug { "Defining #{receiver}._fast_to_json as #{method_body.inspect}" }
|
40
|
+
receiver.instance_eval method_body, cl.absolute_path, cl.lineno
|
43
41
|
end
|
44
42
|
|
45
43
|
# Encoder-compatible with default MultiJSON adapters and defaults
|
@@ -47,45 +45,106 @@ module FastMultiJson
|
|
47
45
|
encode_method = String.new(%(def _fast_to_json(object)\n ))
|
48
46
|
encode_method << Result.new {
|
49
47
|
require 'oj'
|
50
|
-
%(::Oj.dump(object, mode: :compat, time_format: :ruby, use_to_json: true))
|
48
|
+
%(::Oj.dump(object, mode: :compat, time_format: :ruby, use_to_json: true, indent: 0))
|
51
49
|
}.rescue {
|
52
50
|
require 'yajl'
|
53
51
|
%(::Yajl::Encoder.encode(object))
|
54
52
|
}.rescue {
|
55
53
|
require 'jrjackson' unless defined?(::JrJackson)
|
56
|
-
|
54
|
+
if ::JrJackson::Json.method(:dump).arity == 1
|
55
|
+
%(::JrJackson::Json.dump(object))
|
56
|
+
else
|
57
|
+
%(::JrJackson::Json.dump(object, ::FastMultiJson::EMPTY_OPTIONS.dup))
|
58
|
+
end
|
57
59
|
}.rescue {
|
58
60
|
require 'json'
|
59
|
-
%(::JSON.fast_generate(object, create_additions: false, quirks_mode:
|
61
|
+
%(::JSON.fast_generate(object, create_additions: false, quirks_mode: false))
|
60
62
|
}.rescue {
|
61
63
|
require 'gson'
|
62
|
-
%(::Gson::Encoder.new(
|
64
|
+
%(::Gson::Encoder.new(::FastMultiJson::EMPTY_OPTIONS.dup).encode(object))
|
63
65
|
}.rescue {
|
64
66
|
require 'active_support/json/encoding'
|
65
67
|
%(::ActiveSupport::JSON.encode(object))
|
66
68
|
}.rescue {
|
67
69
|
warn "No JSON encoder found. Falling back to `object.to_json`"
|
68
|
-
%(object.to_json)
|
70
|
+
%(object.to_json(::JSON::FAST_STATE_PROTOTYPE.to_h))
|
69
71
|
}.value!
|
70
72
|
encode_method << "\nend"
|
71
73
|
end
|
72
74
|
|
73
|
-
def self.
|
74
|
-
_fast_to_json(
|
75
|
-
|
76
|
-
define_to_json(FastMultiJson)
|
77
|
-
_fast_to_json(object)
|
75
|
+
def self.reset_to_json!
|
76
|
+
undef :_fast_to_json if method_defined?(:_fast_to_json)
|
77
|
+
logger.debug { "Undefining #{receiver}._fast_to_json" }
|
78
78
|
end
|
79
79
|
|
80
|
-
def self.
|
80
|
+
def self.define_from_json(receiver)
|
81
81
|
cl = caller_locations[0]
|
82
|
-
method_body =
|
83
|
-
logger.debug { "Defining #{receiver}.
|
82
|
+
method_body = from_json_method
|
83
|
+
logger.debug { "Defining #{receiver}._fast_from_json as #{method_body.inspect}" }
|
84
84
|
receiver.instance_eval method_body, cl.absolute_path, cl.lineno
|
85
85
|
end
|
86
86
|
|
87
|
-
|
88
|
-
|
89
|
-
|
87
|
+
# Decoder-compatible with default MultiJSON adapters and defaults
|
88
|
+
def self.from_json_method
|
89
|
+
decode_method = String.new(%(def _fast_from_json(string)\n ))
|
90
|
+
decode_method << Result.new {
|
91
|
+
require 'oj'
|
92
|
+
%(::Oj.load(string, mode: :strict, symbol_keys: false))
|
93
|
+
}.rescue {
|
94
|
+
require 'yajl'
|
95
|
+
%(::Yajl::Parser.new(symbolize_keys: false).parse(string))
|
96
|
+
}.rescue {
|
97
|
+
require 'jrjackson' unless defined?(::JrJackson)
|
98
|
+
%(::JrJackson::Json.load(string))
|
99
|
+
}.rescue {
|
100
|
+
require 'json'
|
101
|
+
%(::JSON.parse(string, quirks_mode: false, symbolize_names: false))
|
102
|
+
}.rescue {
|
103
|
+
require 'gson'
|
104
|
+
%(::Gson::Decoder.new(::FastMultiJson::EMPTY_OPTIONS.dup).decode(string))
|
105
|
+
}.rescue {
|
106
|
+
require 'active_support/json/decoding'
|
107
|
+
%(::ActiveSupport::JSON.decode(string))
|
108
|
+
}.rescue {
|
109
|
+
fail "No JSON decoder found."
|
110
|
+
}.value!
|
111
|
+
decode_method << "\nend"
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.reset_from_json!
|
115
|
+
undef :_fast_from_json if method_defined?(:_fast_from_json)
|
116
|
+
logger.debug { "Undefining #{receiver}._fast_from_json" }
|
117
|
+
end
|
118
|
+
|
119
|
+
# Result object pattern is from https://johnnunemaker.com/resilience-in-ruby/
|
120
|
+
# e.g. https://github.com/github/github-ds/blob/fbda5389711edfb4c10b6c6bad19311dfcb1bac1/lib/github/result.rb
|
121
|
+
class Result
|
122
|
+
def initialize
|
123
|
+
@value = yield
|
124
|
+
@error = nil
|
125
|
+
rescue LoadError => e
|
126
|
+
@error = e
|
127
|
+
end
|
128
|
+
|
129
|
+
def ok?
|
130
|
+
@error.nil?
|
131
|
+
end
|
132
|
+
|
133
|
+
def value!
|
134
|
+
if ok?
|
135
|
+
@value
|
136
|
+
else
|
137
|
+
raise @error
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def rescue
|
142
|
+
return self if ok?
|
143
|
+
Result.new { yield(@error) }
|
144
|
+
end
|
90
145
|
end
|
146
|
+
private_constant :Result
|
147
|
+
|
148
|
+
EMPTY_OPTIONS = {}.freeze
|
149
|
+
private_constant :EMPTY_OPTIONS
|
91
150
|
end
|
data/scripts/perf_compat
ADDED
@@ -0,0 +1,271 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require 'bundler/inline'
|
5
|
+
|
6
|
+
gemfile do
|
7
|
+
source 'https://rubygems.org'
|
8
|
+
gem 'multi_json', require: false
|
9
|
+
gem 'oj', require: false
|
10
|
+
gem 'fast_multi_json', path: '.'
|
11
|
+
end
|
12
|
+
|
13
|
+
# Adapted from https://raw.githubusercontent.com/ohler55/oj/39c975a048d89f42062bb542fae98109520b10eb/test/perf.rb
|
14
|
+
class Perf
|
15
|
+
|
16
|
+
def initialize()
|
17
|
+
@items = []
|
18
|
+
end
|
19
|
+
|
20
|
+
def add(title, op, &blk)
|
21
|
+
@items << Item.new(title, op, &blk)
|
22
|
+
end
|
23
|
+
|
24
|
+
def before(title, &blk)
|
25
|
+
@items.each do |i|
|
26
|
+
if title == i.title
|
27
|
+
i.set_before(&blk)
|
28
|
+
break
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def run(iter)
|
34
|
+
base = Item.new(nil, nil) { }
|
35
|
+
base.run(iter, 0.0)
|
36
|
+
@items.each do |i|
|
37
|
+
i.run(iter, base.duration)
|
38
|
+
if i.error.nil?
|
39
|
+
puts "#{i.title}.#{i.op} #{iter} times in %0.3f seconds or %0.3f #{i.op}/sec." % [i.duration, iter / i.duration]
|
40
|
+
else
|
41
|
+
puts "***** #{i.title}.#{i.op} failed! #{i.error}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
summary()
|
45
|
+
end
|
46
|
+
|
47
|
+
def summary()
|
48
|
+
fastest = nil
|
49
|
+
slowest = nil
|
50
|
+
width = 6
|
51
|
+
@items.each do |i|
|
52
|
+
next if i.duration.nil?
|
53
|
+
width = i.title.size if width < i.title.size
|
54
|
+
end
|
55
|
+
iva = @items.clone
|
56
|
+
iva.delete_if { |i| i.duration.nil? }
|
57
|
+
iva = iva.sort_by { |i| i.duration }
|
58
|
+
puts
|
59
|
+
puts "Summary:"
|
60
|
+
puts "%*s time (secs) rate (ops/sec)" % [width, 'System']
|
61
|
+
puts "#{'-' * width} ----------- --------------"
|
62
|
+
iva.each do |i|
|
63
|
+
if i.duration.nil?
|
64
|
+
else
|
65
|
+
puts "%*s %11.3f %14.3f" % [width, i.title, i.duration, i.rate ]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
puts
|
69
|
+
puts "Comparison Matrix\n(performance factor, 2.0 means row is twice as fast as column)"
|
70
|
+
puts ([' ' * width] + iva.map { |i| "%*s" % [width, i.title] }).join(' ')
|
71
|
+
puts (['-' * width] + iva.map { |i| '-' * width }).join(' ')
|
72
|
+
iva.each do |i|
|
73
|
+
line = ["%*s" % [width, i.title]]
|
74
|
+
iva.each do |o|
|
75
|
+
line << "%*.2f" % [width, o.duration / i.duration]
|
76
|
+
end
|
77
|
+
puts line.join(' ')
|
78
|
+
end
|
79
|
+
puts
|
80
|
+
end
|
81
|
+
|
82
|
+
class Item
|
83
|
+
attr_accessor :title
|
84
|
+
attr_accessor :op
|
85
|
+
attr_accessor :blk
|
86
|
+
attr_accessor :duration
|
87
|
+
attr_accessor :rate
|
88
|
+
attr_accessor :error
|
89
|
+
|
90
|
+
def initialize(title, op, &blk)
|
91
|
+
@title = title
|
92
|
+
@blk = blk
|
93
|
+
@op = op
|
94
|
+
@duration = nil
|
95
|
+
@rate = nil
|
96
|
+
@error = nil
|
97
|
+
@before = nil
|
98
|
+
end
|
99
|
+
|
100
|
+
def set_before(&blk)
|
101
|
+
@before = blk
|
102
|
+
end
|
103
|
+
|
104
|
+
def run(iter, base)
|
105
|
+
begin
|
106
|
+
GC.start
|
107
|
+
@before.call unless @before.nil?
|
108
|
+
start = Time.now
|
109
|
+
iter.times { @blk.call }
|
110
|
+
@duration = Time.now - start - base
|
111
|
+
@duration = 0.0 if @duration < 0.0
|
112
|
+
@rate = iter / @duration
|
113
|
+
rescue Exception => e
|
114
|
+
@error = "#{e.class}: #{e.message}"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end # Item
|
119
|
+
end # Perf
|
120
|
+
|
121
|
+
|
122
|
+
# Adapted from https://github.com/ohler55/oj/blob/39c975a048d89f42062bb542fae98109520b10eb/test/perf_compat.rb
|
123
|
+
require 'optparse'
|
124
|
+
require 'oj'
|
125
|
+
require 'fast_multi_json'
|
126
|
+
require 'multi_json'
|
127
|
+
|
128
|
+
$verbose = false
|
129
|
+
$indent = 0
|
130
|
+
$iter = 20000
|
131
|
+
$size = 0
|
132
|
+
|
133
|
+
opts = OptionParser.new
|
134
|
+
opts.on("-v", "verbose") { $verbose = true }
|
135
|
+
opts.on("-c", "--count [Int]", Integer, "iterations") { |i| $iter = i }
|
136
|
+
opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
|
137
|
+
opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") { |i| $size = i }
|
138
|
+
opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
|
139
|
+
files = opts.parse(ARGV)
|
140
|
+
|
141
|
+
def capture_error(tag, orig, load_key, dump_key, &blk)
|
142
|
+
begin
|
143
|
+
obj = blk.call(orig)
|
144
|
+
puts obj unless orig == obj
|
145
|
+
raise "#{tag} #{dump_key} and #{load_key} did not return the same object as the original." unless orig == obj
|
146
|
+
rescue Exception => e
|
147
|
+
$failed[tag] = "#{e.class}: #{e.message}"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
$failed = {} # key is same as String used in tests later
|
152
|
+
|
153
|
+
# Verify that all packages dump and load correctly and return the same Object as the original.
|
154
|
+
capture_error('Oj:compat', $obj, 'load', 'dump') { |o| Oj.compat_load(Oj.dump(o, :mode => :compat)) }
|
155
|
+
capture_error('MultiJson', $obj, 'load', 'dump') { |o| MultiJson.load(MultiJson.dump(o)) }
|
156
|
+
capture_error('FastMultiJson', $obj, 'oj_load', 'dump') { |o| FastMultiJson.from_json(FastMultiJson.to_json(o)) }
|
157
|
+
capture_error('JSON::Ext', $obj, 'generate', 'parse') { |o|
|
158
|
+
require 'json'
|
159
|
+
require 'json/ext'
|
160
|
+
JSON.generator = JSON::Ext::Generator
|
161
|
+
JSON.parser = JSON::Ext::Parser
|
162
|
+
JSON.load(JSON.generate(o))
|
163
|
+
}
|
164
|
+
|
165
|
+
module One
|
166
|
+
module Two
|
167
|
+
module Three
|
168
|
+
class Empty
|
169
|
+
|
170
|
+
def initialize()
|
171
|
+
@a = 1
|
172
|
+
@b = 2
|
173
|
+
@c = 3
|
174
|
+
end
|
175
|
+
|
176
|
+
def eql?(o)
|
177
|
+
self.class == o.class && @a == o.a && @b = o.b && @c = o.c
|
178
|
+
end
|
179
|
+
alias == eql?
|
180
|
+
|
181
|
+
def as_json(*a)
|
182
|
+
{JSON.create_id => self.class.name, 'a' => @a, 'b' => @b, 'c' => @c }
|
183
|
+
end
|
184
|
+
|
185
|
+
def to_json(*a)
|
186
|
+
JSON.generate(as_json())
|
187
|
+
end
|
188
|
+
|
189
|
+
def self.json_create(h)
|
190
|
+
self.new()
|
191
|
+
end
|
192
|
+
end # Empty
|
193
|
+
end # Three
|
194
|
+
end # Two
|
195
|
+
end # One
|
196
|
+
|
197
|
+
$obj = {
|
198
|
+
'a' => 'Alpha', # string
|
199
|
+
'b' => true, # boolean
|
200
|
+
'c' => 12345, # number
|
201
|
+
'd' => [ true, [false, [-123456789, nil], 3.9676, ['Something else.', false], nil]], # mix it up array
|
202
|
+
'e' => { 'zero' => nil, 'one' => 1, 'two' => 2, 'three' => [3], 'four' => [0, 1, 2, 3, 4] }, # hash
|
203
|
+
'f' => nil, # nil
|
204
|
+
'g' => One::Two::Three::Empty.new(),
|
205
|
+
'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
|
206
|
+
'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
|
207
|
+
}
|
208
|
+
|
209
|
+
|
210
|
+
Oj.default_options = { :indent => $indent, :mode => :compat, :use_to_json => true, :create_additions => true, :create_id => '^o' }
|
211
|
+
|
212
|
+
if 0 < $size
|
213
|
+
s = Oj.dump($obj).size + 1
|
214
|
+
cnt = $size * 1024 / s
|
215
|
+
o = $obj
|
216
|
+
$obj = []
|
217
|
+
cnt.times do
|
218
|
+
$obj << o
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
puts '-' * 80
|
223
|
+
puts " ## Compat dump Performance"
|
224
|
+
perf = Perf.new()
|
225
|
+
unless $failed.has_key?('JSON::Ext')
|
226
|
+
perf.add('JSON::Ext', 'dump') { JSON.dump($obj) }
|
227
|
+
perf.before('JSON::Ext') { JSON.parser = JSON::Ext::Parser }
|
228
|
+
end
|
229
|
+
unless $failed.has_key?('MultiJson')
|
230
|
+
perf.add('MultiJson', 'dump') { MultiJson.dump($oj) }
|
231
|
+
end
|
232
|
+
unless $failed.has_key?('FastMultiJson')
|
233
|
+
perf.add('FastMultiJson', 'to_json') { FastMultiJson.to_json($oj) }
|
234
|
+
end
|
235
|
+
unless $failed.has_key?('Oj:compat')
|
236
|
+
perf.add('Oj:compat', 'dump_compat') { Oj.dump($oj, mode: :compat) }
|
237
|
+
end
|
238
|
+
perf.run($iter)
|
239
|
+
|
240
|
+
puts
|
241
|
+
puts '-' * 80
|
242
|
+
puts
|
243
|
+
|
244
|
+
$json = JSON.dump($obj)
|
245
|
+
|
246
|
+
puts '-' * 80
|
247
|
+
puts " ## Compat load Performance"
|
248
|
+
perf = Perf.new()
|
249
|
+
unless $failed.has_key?('JSON::Ext')
|
250
|
+
perf.add('JSON::Ext', 'load') { JSON.load($json) }
|
251
|
+
perf.before('JSON::Ext') { JSON.parser = JSON::Ext::Parser }
|
252
|
+
end
|
253
|
+
unless $failed.has_key?('MultiJson')
|
254
|
+
perf.add('MultiJson', 'load') { MultiJson.load($json) }
|
255
|
+
end
|
256
|
+
unless $failed.has_key?('FastMultiJson')
|
257
|
+
perf.add('FastMultiJson', 'from_json') { FastMultiJson.from_json($json) }
|
258
|
+
end
|
259
|
+
unless $failed.has_key?('Oj:compat')
|
260
|
+
perf.add('Oj:compat', 'load_compat') { Oj.load($json, mode: :compat) }
|
261
|
+
end
|
262
|
+
perf.run($iter)
|
263
|
+
|
264
|
+
puts
|
265
|
+
puts '-' * 80
|
266
|
+
puts
|
267
|
+
|
268
|
+
unless $failed.empty?
|
269
|
+
puts "The following packages were not included for the reason listed"
|
270
|
+
$failed.each { |tag,msg| puts "***** #{tag}: #{msg}" }
|
271
|
+
end
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fast_multi_json
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benjamin Fleischer
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-06-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -76,12 +76,13 @@ files:
|
|
76
76
|
- fast_multi_json.gemspec
|
77
77
|
- lib/fast_multi_json.rb
|
78
78
|
- lib/fast_multi_json/version.rb
|
79
|
+
- scripts/perf_compat
|
79
80
|
homepage: https://github.com/bf4/fast_multi_json
|
80
81
|
licenses:
|
81
82
|
- MIT
|
82
83
|
metadata:
|
83
84
|
allowed_push_host: https://rubygems.org
|
84
|
-
post_install_message:
|
85
|
+
post_install_message:
|
85
86
|
rdoc_options: []
|
86
87
|
require_paths:
|
87
88
|
- lib
|
@@ -96,9 +97,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
97
|
- !ruby/object:Gem::Version
|
97
98
|
version: '0'
|
98
99
|
requirements: []
|
99
|
-
|
100
|
-
|
101
|
-
signing_key:
|
100
|
+
rubygems_version: 3.3.7
|
101
|
+
signing_key:
|
102
102
|
specification_version: 4
|
103
103
|
summary: Adapterless multi-JSON encoder/decoder
|
104
104
|
test_files: []
|