fast_multi_json 1.0.0 → 1.1.0
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.
- 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: []
|