Module: Iodine::JSON

Defined in:
lib/iodine/json.rb,
ext/iodine/iodine_json.c

Overview

Iodine includes a lenient JSON parser that attempts to ignore JSON errors when possible and adds some extensions such as Hex numerical representations and comments.

On my system, the Iodine JSON parser is more than 40% faster than the native Ruby parser. When using symbols the speed increase is even higher.

It’s easy to monkey-patch the system’s ‘JSON.parse` method (not the `JSON.parse!` method) by using `Iodine.patch_json`.

You can benchmark the Iodine JSON performance and decide if you wish to monkey-patch the Ruby implementation.

JSON_FILENAME="foo.json"

require 'json'
require 'iodine'
TIMES = 100
STR = IO.binread(JSON_FILENAME); nil

JSON.parse(STR) == Iodine::JSON.parse(STR) # => true
JSON.parse!(STR) == Iodine::JSON.parse!(STR) # => undefined, maybe true maybe false

# warm-up
TIMES.times { JSON.parse STR }
TIMES.times { Iodine::JSON.parse STR }

puts ""; Benchmark.bm do |b|
  sys = b.report("system") { TIMES.times { JSON.parse STR } }
  sys_sym = b.report("system-sym") { TIMES.times { JSON.parse STR, symbolize_names: true } }
  iodine = b.report("iodine") { TIMES.times { Iodine::JSON.parse STR } }
  iodine_sym = b.report("iodine-sym") { TIMES.times { Iodine::JSON.parse STR, symbolize_names: true } }

  puts "----------------------------"
  puts "Iodine::JSON speed as percent of Ruby's native JSON:"
  puts "normal:    #{sys/iodine}"
  puts "symolized: #{sys_sym/iodine_sym}"
end; nil

Note that the bang(!) method should NOT be used for monkey-patching the default JSON parser, since some important features are unsupported by the Iodine parser.

Class Method Summary collapse

Class Method Details

.parse(*args) ⇒ Object

Parse a JSON string using the iodine lenient parser (it’s also faster).



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'ext/iodine/iodine_json.c', line 219

static VALUE iodine_json_parse(int argc, VALUE *argv, VALUE self) {
  fiobj2rb_settings_s s = {.str2sym = 0};
  if (argc > 2)
    rb_raise(rb_eTypeError, "function requires supports up to two arguments.");
  if (argc == 2) {
    Check_Type(argv[1], T_HASH);
    iodine_json_update_settings(argv[1], &s);
  }
  if (argc >= 1)
    Check_Type(argv[0], T_STRING);
  else
    rb_raise(rb_eTypeError, "function requires at least one argument.");
  return iodine_json_convert(argv[0], s);
  (void)self;
}

.parse!(*args) ⇒ Object

Parse a JSON string using the iodine lenient parser with a default Symbol rather than String key (this is often faster than the regular parse function).



240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'ext/iodine/iodine_json.c', line 240

static VALUE iodine_json_parse_bang(int argc, VALUE *argv, VALUE self) {
  fiobj2rb_settings_s s = {.str2sym = 0};
  if (argc > 2)
    rb_raise(rb_eTypeError, "function requires supports up to two arguments.");
  if (argc == 2) {
    Check_Type(argv[1], T_HASH);
    iodine_json_update_settings(argv[1], &s);
  }
  if (argc >= 1)
    Check_Type(argv[0], T_STRING);
  else
    rb_raise(rb_eTypeError, "function requires at least one argument.");
  return iodine_json_convert(argv[0], s);
  (void)self;
}