oj 3.15.0 → 3.16.3
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 +4 -4
- data/CHANGELOG.md +29 -0
- data/ext/oj/cache.c +4 -2
- data/ext/oj/cache.h +3 -2
- data/ext/oj/code.c +3 -10
- data/ext/oj/compat.c +5 -18
- data/ext/oj/custom.c +5 -13
- data/ext/oj/dump.c +30 -22
- data/ext/oj/dump.h +1 -4
- data/ext/oj/dump_compat.c +16 -16
- data/ext/oj/extconf.rb +4 -2
- data/ext/oj/fast.c +10 -12
- data/ext/oj/intern.c +23 -6
- data/ext/oj/mimic_json.c +3 -6
- data/ext/oj/object.c +13 -5
- data/ext/oj/oj.c +155 -132
- data/ext/oj/oj.h +26 -33
- data/ext/oj/parse.c +7 -5
- data/ext/oj/parse.h +16 -14
- data/ext/oj/parser.c +61 -50
- data/ext/oj/parser.h +2 -2
- data/ext/oj/rails.c +23 -7
- data/ext/oj/reader.c +1 -3
- data/ext/oj/saj.c +1 -1
- data/ext/oj/stream_writer.c +35 -15
- data/ext/oj/string_writer.c +50 -17
- data/ext/oj/usual.c +20 -0
- data/ext/oj/usual.h +1 -0
- data/ext/oj/val_stack.c +13 -2
- data/lib/oj/active_support_helper.rb +2 -3
- data/lib/oj/json.rb +159 -149
- data/lib/oj/mimic.rb +3 -1
- data/lib/oj/version.rb +1 -1
- data/test/foo.rb +3 -4
- data/test/json_gem/json_common_interface_test.rb +4 -2
- data/test/json_gem/json_generator_test.rb +7 -1
- data/test/perf_dump.rb +3 -3
- data/test/prec.rb +4 -4
- data/test/test_compat.rb +19 -1
- data/test/test_custom.rb +2 -1
- data/test/test_object.rb +14 -0
- data/test/test_parser_debug.rb +1 -1
- data/test/test_parser_usual.rb +10 -0
- data/test/test_strict.rb +10 -0
- data/test/test_various.rb +6 -0
- metadata +17 -3
data/ext/oj/string_writer.c
CHANGED
@@ -70,7 +70,6 @@ void oj_str_writer_init(StrWriter sw, int buf_size) {
|
|
70
70
|
sw->out.depth = 0;
|
71
71
|
sw->out.argc = 0;
|
72
72
|
sw->out.argv = NULL;
|
73
|
-
sw->out.caller = 0;
|
74
73
|
sw->out.ropts = NULL;
|
75
74
|
sw->out.omit_nil = oj_default_options.dump_opts.omit_nil;
|
76
75
|
}
|
@@ -226,7 +225,7 @@ void oj_str_writer_pop_all(StrWriter sw) {
|
|
226
225
|
}
|
227
226
|
}
|
228
227
|
|
229
|
-
static void
|
228
|
+
static void string_writer_free(void *ptr) {
|
230
229
|
StrWriter sw;
|
231
230
|
|
232
231
|
if (0 == ptr) {
|
@@ -240,6 +239,23 @@ static void str_writer_free(void *ptr) {
|
|
240
239
|
OJ_R_FREE(ptr);
|
241
240
|
}
|
242
241
|
|
242
|
+
static const rb_data_type_t oj_string_writer_type = {
|
243
|
+
"Oj/string_writer",
|
244
|
+
{
|
245
|
+
NULL,
|
246
|
+
string_writer_free,
|
247
|
+
NULL,
|
248
|
+
},
|
249
|
+
0,
|
250
|
+
0,
|
251
|
+
};
|
252
|
+
|
253
|
+
StrWriter oj_str_writer_unwrap(VALUE writer) {
|
254
|
+
StrWriter sw;
|
255
|
+
TypedData_Get_Struct(writer, struct _strWriter, &oj_string_writer_type, sw);
|
256
|
+
return sw;
|
257
|
+
}
|
258
|
+
|
243
259
|
/* Document-method: new
|
244
260
|
* call-seq: new(io, options)
|
245
261
|
*
|
@@ -267,7 +283,7 @@ static VALUE str_writer_new(int argc, VALUE *argv, VALUE self) {
|
|
267
283
|
sw->out.argv = argv + 1;
|
268
284
|
sw->out.indent = sw->opts.indent;
|
269
285
|
|
270
|
-
return
|
286
|
+
return TypedData_Wrap_Struct(oj_string_writer_class, &oj_string_writer_type, sw);
|
271
287
|
}
|
272
288
|
|
273
289
|
/* Document-method: push_key
|
@@ -279,7 +295,8 @@ static VALUE str_writer_new(int argc, VALUE *argv, VALUE self) {
|
|
279
295
|
* - *key* [_String_] the key pending for the next push
|
280
296
|
*/
|
281
297
|
static VALUE str_writer_push_key(VALUE self, VALUE key) {
|
282
|
-
StrWriter sw
|
298
|
+
StrWriter sw;
|
299
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
283
300
|
|
284
301
|
oj_str_writer_push_key(sw, StringValuePtr(key));
|
285
302
|
|
@@ -294,7 +311,8 @@ static VALUE str_writer_push_key(VALUE self, VALUE key) {
|
|
294
311
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
295
312
|
*/
|
296
313
|
static VALUE str_writer_push_object(int argc, VALUE *argv, VALUE self) {
|
297
|
-
StrWriter sw
|
314
|
+
StrWriter sw;
|
315
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
298
316
|
|
299
317
|
switch (argc) {
|
300
318
|
case 0: oj_str_writer_push_object(sw, 0); break;
|
@@ -322,7 +340,8 @@ static VALUE str_writer_push_object(int argc, VALUE *argv, VALUE self) {
|
|
322
340
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
323
341
|
*/
|
324
342
|
static VALUE str_writer_push_array(int argc, VALUE *argv, VALUE self) {
|
325
|
-
StrWriter sw
|
343
|
+
StrWriter sw;
|
344
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
326
345
|
|
327
346
|
switch (argc) {
|
328
347
|
case 0: oj_str_writer_push_array(sw, 0); break;
|
@@ -350,13 +369,16 @@ static VALUE str_writer_push_array(int argc, VALUE *argv, VALUE self) {
|
|
350
369
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
351
370
|
*/
|
352
371
|
static VALUE str_writer_push_value(int argc, VALUE *argv, VALUE self) {
|
372
|
+
StrWriter sw;
|
373
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
374
|
+
|
353
375
|
switch (argc) {
|
354
|
-
case 1: oj_str_writer_push_value(
|
376
|
+
case 1: oj_str_writer_push_value(sw, *argv, 0); break;
|
355
377
|
case 2:
|
356
378
|
if (Qnil == argv[1]) {
|
357
|
-
oj_str_writer_push_value(
|
379
|
+
oj_str_writer_push_value(sw, *argv, 0);
|
358
380
|
} else {
|
359
|
-
oj_str_writer_push_value(
|
381
|
+
oj_str_writer_push_value(sw, *argv, StringValuePtr(argv[1]));
|
360
382
|
}
|
361
383
|
break;
|
362
384
|
default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_value'."); break;
|
@@ -374,13 +396,16 @@ static VALUE str_writer_push_value(int argc, VALUE *argv, VALUE self) {
|
|
374
396
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
375
397
|
*/
|
376
398
|
static VALUE str_writer_push_json(int argc, VALUE *argv, VALUE self) {
|
399
|
+
StrWriter sw;
|
400
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
401
|
+
|
377
402
|
switch (argc) {
|
378
|
-
case 1: oj_str_writer_push_json(
|
403
|
+
case 1: oj_str_writer_push_json(sw, StringValuePtr(*argv), 0); break;
|
379
404
|
case 2:
|
380
405
|
if (Qnil == argv[1]) {
|
381
|
-
oj_str_writer_push_json(
|
406
|
+
oj_str_writer_push_json(sw, StringValuePtr(*argv), 0);
|
382
407
|
} else {
|
383
|
-
oj_str_writer_push_json(
|
408
|
+
oj_str_writer_push_json(sw, StringValuePtr(*argv), StringValuePtr(argv[1]));
|
384
409
|
}
|
385
410
|
break;
|
386
411
|
default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_json'."); break;
|
@@ -394,7 +419,10 @@ static VALUE str_writer_push_json(int argc, VALUE *argv, VALUE self) {
|
|
394
419
|
* currently open.
|
395
420
|
*/
|
396
421
|
static VALUE str_writer_pop(VALUE self) {
|
397
|
-
|
422
|
+
StrWriter sw;
|
423
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
424
|
+
|
425
|
+
oj_str_writer_pop(sw);
|
398
426
|
return Qnil;
|
399
427
|
}
|
400
428
|
|
@@ -405,7 +433,10 @@ static VALUE str_writer_pop(VALUE self) {
|
|
405
433
|
* currently open.
|
406
434
|
*/
|
407
435
|
static VALUE str_writer_pop_all(VALUE self) {
|
408
|
-
|
436
|
+
StrWriter sw;
|
437
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
438
|
+
|
439
|
+
oj_str_writer_pop_all(sw);
|
409
440
|
|
410
441
|
return Qnil;
|
411
442
|
}
|
@@ -416,7 +447,8 @@ static VALUE str_writer_pop_all(VALUE self) {
|
|
416
447
|
* Reset the writer back to the empty state.
|
417
448
|
*/
|
418
449
|
static VALUE str_writer_reset(VALUE self) {
|
419
|
-
StrWriter sw
|
450
|
+
StrWriter sw;
|
451
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
420
452
|
|
421
453
|
sw->depth = 0;
|
422
454
|
*sw->types = '\0';
|
@@ -435,8 +467,9 @@ static VALUE str_writer_reset(VALUE self) {
|
|
435
467
|
* *return* [_String_]
|
436
468
|
*/
|
437
469
|
static VALUE str_writer_to_s(VALUE self) {
|
438
|
-
StrWriter sw
|
439
|
-
|
470
|
+
StrWriter sw;
|
471
|
+
TypedData_Get_Struct(self, struct _strWriter, &oj_string_writer_type, sw);
|
472
|
+
VALUE rstr = rb_str_new(sw->out.buf, sw->out.cur - sw->out.buf);
|
440
473
|
|
441
474
|
return oj_encode(rstr);
|
442
475
|
}
|
data/ext/oj/usual.c
CHANGED
@@ -601,6 +601,9 @@ static VALUE result(ojParser p) {
|
|
601
601
|
if (d->vhead < d->vtail) {
|
602
602
|
return *d->vhead;
|
603
603
|
}
|
604
|
+
if (d->raise_on_empty) {
|
605
|
+
rb_raise(oj_parse_error_class, "empty string");
|
606
|
+
}
|
604
607
|
return Qnil;
|
605
608
|
}
|
606
609
|
|
@@ -1066,6 +1069,20 @@ static VALUE opt_symbol_keys_set(ojParser p, VALUE value) {
|
|
1066
1069
|
return (NULL != d->sym_cache) ? Qtrue : Qfalse;
|
1067
1070
|
}
|
1068
1071
|
|
1072
|
+
static VALUE opt_raise_on_empty(ojParser p, VALUE value) {
|
1073
|
+
Usual d = (Usual)p->ctx;
|
1074
|
+
|
1075
|
+
return d->raise_on_empty ? Qtrue : Qfalse;
|
1076
|
+
}
|
1077
|
+
|
1078
|
+
static VALUE opt_raise_on_empty_set(ojParser p, VALUE value) {
|
1079
|
+
Usual d = (Usual)p->ctx;
|
1080
|
+
|
1081
|
+
d->raise_on_empty = (Qtrue == value);
|
1082
|
+
|
1083
|
+
return d->raise_on_empty ? Qtrue : Qfalse;
|
1084
|
+
}
|
1085
|
+
|
1069
1086
|
static VALUE option(ojParser p, const char *key, VALUE value) {
|
1070
1087
|
struct opt *op;
|
1071
1088
|
struct opt opts[] = {
|
@@ -1095,6 +1112,8 @@ static VALUE option(ojParser p, const char *key, VALUE value) {
|
|
1095
1112
|
{.name = "omit_null=", .func = opt_omit_null_set},
|
1096
1113
|
{.name = "symbol_keys", .func = opt_symbol_keys},
|
1097
1114
|
{.name = "symbol_keys=", .func = opt_symbol_keys_set},
|
1115
|
+
{.name = "raise_on_empty", .func = opt_raise_on_empty},
|
1116
|
+
{.name = "raise_on_empty=", .func = opt_raise_on_empty_set},
|
1098
1117
|
{.name = NULL},
|
1099
1118
|
};
|
1100
1119
|
|
@@ -1129,6 +1148,7 @@ void oj_init_usual(ojParser p, Usual d) {
|
|
1129
1148
|
d->get_key = cache_key;
|
1130
1149
|
d->cache_keys = true;
|
1131
1150
|
d->ignore_json_create = false;
|
1151
|
+
d->raise_on_empty = false;
|
1132
1152
|
d->cache_str = 6;
|
1133
1153
|
d->array_class = Qnil;
|
1134
1154
|
d->hash_class = Qnil;
|
data/ext/oj/usual.h
CHANGED
data/ext/oj/val_stack.c
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
#include "odd.h"
|
9
9
|
#include "oj.h"
|
10
10
|
|
11
|
-
static void
|
11
|
+
static void stack_mark(void *ptr) {
|
12
12
|
ValStack stack = (ValStack)ptr;
|
13
13
|
Val v;
|
14
14
|
|
@@ -46,6 +46,17 @@ static void mark(void *ptr) {
|
|
46
46
|
#endif
|
47
47
|
}
|
48
48
|
|
49
|
+
static const rb_data_type_t oj_stack_type = {
|
50
|
+
"Oj/stack",
|
51
|
+
{
|
52
|
+
stack_mark,
|
53
|
+
NULL,
|
54
|
+
NULL,
|
55
|
+
},
|
56
|
+
0,
|
57
|
+
0,
|
58
|
+
};
|
59
|
+
|
49
60
|
VALUE
|
50
61
|
oj_stack_init(ValStack stack) {
|
51
62
|
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
@@ -70,7 +81,7 @@ oj_stack_init(ValStack stack) {
|
|
70
81
|
stack->head->clen = 0;
|
71
82
|
stack->head->next = NEXT_NONE;
|
72
83
|
|
73
|
-
return
|
84
|
+
return TypedData_Wrap_Struct(oj_cstack_class, &oj_stack_type, stack);
|
74
85
|
}
|
75
86
|
|
76
87
|
const char *oj_stack_next_string(ValNext n) {
|
@@ -1,15 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support/time'
|
2
4
|
|
3
5
|
module Oj
|
4
|
-
|
5
6
|
# Exists only to handle the ActiveSupport::TimeWithZone.
|
6
7
|
class ActiveSupportHelper
|
7
|
-
|
8
8
|
def self.createTimeWithZone(utc, zone)
|
9
9
|
ActiveSupport::TimeWithZone.new(utc - utc.gmt_offset, ActiveSupport::TimeZone[zone])
|
10
10
|
end
|
11
11
|
end
|
12
|
-
|
13
12
|
end
|
14
13
|
|
15
14
|
Oj.register_odd(ActiveSupport::TimeWithZone, Oj::ActiveSupportHelper, :createTimeWithZone, :utc, 'time_zone.name')
|
data/lib/oj/json.rb
CHANGED
@@ -1,178 +1,188 @@
|
|
1
1
|
require 'ostruct'
|
2
2
|
require 'oj/state'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
4
|
+
if defined?(JSON::PRETTY_STATE_PROTOTYPE)
|
5
|
+
# There are enough people that try to use both the json gen and oj in mimic
|
6
|
+
# mode so don't display the warning.
|
7
|
+
|
8
|
+
# warn "WARNING: oj/json is a compatability shim used by Oj. Requiring the file explicitly is not recommended."
|
9
|
+
end
|
10
|
+
|
11
|
+
unless defined?(JSON::PRETTY_STATE_PROTOTYPE)
|
12
|
+
module JSON
|
13
|
+
NaN = 0.0/0.0 unless defined?(::JSON::NaN)
|
14
|
+
Infinity = 1.0/0.0 unless defined?(::JSON::Infinity)
|
15
|
+
MinusInfinity = -1.0/0.0 unless defined?(::JSON::MinusInfinity)
|
16
|
+
# Taken from the unit test. Note that items like check_circular? are not
|
17
|
+
# present.
|
18
|
+
PRETTY_STATE_PROTOTYPE = Ext::Generator::State.from_state({
|
19
|
+
:allow_nan => false,
|
20
|
+
:array_nl => "\n",
|
21
|
+
:ascii_only => false,
|
22
|
+
:buffer_initial_length => 1024,
|
23
|
+
:depth => 0,
|
24
|
+
:indent => " ",
|
25
|
+
:max_nesting => 100,
|
26
|
+
:object_nl => "\n",
|
27
|
+
:space => " ",
|
28
|
+
:space_before => "",
|
29
|
+
}) unless defined?(::JSON::PRETTY_STATE_PROTOTYPE)
|
30
|
+
SAFE_STATE_PROTOTYPE = Ext::Generator::State.from_state({
|
31
|
+
:allow_nan => false,
|
32
|
+
:array_nl => "",
|
33
|
+
:ascii_only => false,
|
34
|
+
:buffer_initial_length => 1024,
|
35
|
+
:depth => 0,
|
36
|
+
:indent => "",
|
37
|
+
:max_nesting => 100,
|
38
|
+
:object_nl => "",
|
39
|
+
:space => "",
|
40
|
+
:space_before => "",
|
41
|
+
}) unless defined?(::JSON::SAFE_STATE_PROTOTYPE)
|
42
|
+
FAST_STATE_PROTOTYPE = Ext::Generator::State.from_state({
|
43
|
+
:allow_nan => false,
|
44
|
+
:array_nl => "",
|
45
|
+
:ascii_only => false,
|
46
|
+
:buffer_initial_length => 1024,
|
47
|
+
:depth => 0,
|
48
|
+
:indent => "",
|
49
|
+
:max_nesting => 0,
|
50
|
+
:object_nl => "",
|
51
|
+
:space => "",
|
52
|
+
:space_before => "",
|
53
|
+
}) unless defined?(::JSON::FAST_STATE_PROTOTYPE)
|
54
|
+
|
55
|
+
def self.dump_default_options
|
56
|
+
Oj::MimicDumpOption.new
|
55
57
|
end
|
56
|
-
end
|
57
58
|
|
58
|
-
|
59
|
-
|
60
|
-
|
59
|
+
def self.dump_default_options=(h)
|
60
|
+
m = Oj::MimicDumpOption.new
|
61
|
+
h.each do |k, v|
|
62
|
+
m[k] = v
|
63
|
+
end
|
64
|
+
end
|
61
65
|
|
62
|
-
|
63
|
-
|
64
|
-
|
66
|
+
def self.parser=(p)
|
67
|
+
@@parser = p
|
68
|
+
end
|
65
69
|
|
66
|
-
|
67
|
-
|
68
|
-
|
70
|
+
def self.parser()
|
71
|
+
@@parser
|
72
|
+
end
|
69
73
|
|
70
|
-
|
71
|
-
|
72
|
-
|
74
|
+
def self.generator=(g)
|
75
|
+
@@generator = g
|
76
|
+
end
|
73
77
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
raise TypeError.new("already initialized") unless @source.nil?
|
78
|
+
def self.generator()
|
79
|
+
@@generator
|
80
|
+
end
|
78
81
|
|
79
|
-
|
80
|
-
|
82
|
+
module Ext
|
83
|
+
class Parser
|
84
|
+
def initialize(src)
|
85
|
+
raise TypeError.new("already initialized") unless @source.nil?
|
81
86
|
|
82
|
-
|
83
|
-
|
87
|
+
@source = src
|
88
|
+
end
|
84
89
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
def parse()
|
89
|
-
raise TypeError.new("already initialized") if @source.nil?
|
90
|
+
def source()
|
91
|
+
raise TypeError.new("already initialized") if @source.nil?
|
90
92
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
end # Parser
|
95
|
-
end # Ext
|
96
|
-
|
97
|
-
State = ::JSON::Ext::Generator::State unless defined?(::JSON::State)
|
98
|
-
|
99
|
-
begin
|
100
|
-
send(:remove_const, :Parser)
|
101
|
-
rescue
|
102
|
-
end
|
103
|
-
Parser = ::JSON::Ext::Parser unless defined?(::JSON::Parser)
|
104
|
-
self.parser = ::JSON::Ext::Parser
|
105
|
-
self.generator = ::JSON::Ext::Generator
|
106
|
-
|
107
|
-
# Taken directly from the json gem. Shamelessly copied. It is similar in
|
108
|
-
# some ways to the Oj::Bag class or the Oj::EasyHash class.
|
109
|
-
class GenericObject < OpenStruct
|
110
|
-
class << self
|
111
|
-
alias [] new
|
112
|
-
|
113
|
-
def json_creatable?
|
114
|
-
@json_creatable
|
115
|
-
end
|
93
|
+
@source
|
94
|
+
end
|
116
95
|
|
117
|
-
|
96
|
+
def parse()
|
97
|
+
raise TypeError.new("already initialized") if @source.nil?
|
118
98
|
|
119
|
-
|
120
|
-
|
121
|
-
data.delete JSON.create_id
|
122
|
-
self[data]
|
123
|
-
end
|
99
|
+
JSON.parse(@source)
|
100
|
+
end
|
124
101
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
102
|
+
end # Parser
|
103
|
+
end # Ext
|
104
|
+
|
105
|
+
State = ::JSON::Ext::Generator::State unless defined?(::JSON::State)
|
106
|
+
|
107
|
+
begin
|
108
|
+
send(:remove_const, :Parser)
|
109
|
+
rescue
|
110
|
+
# ignore and move on
|
111
|
+
end
|
112
|
+
Parser = ::JSON::Ext::Parser unless defined?(::JSON::Parser)
|
113
|
+
self.parser = ::JSON::Ext::Parser
|
114
|
+
self.generator = ::JSON::Ext::Generator
|
115
|
+
|
116
|
+
# Taken directly from the json gem. Shamelessly copied. It is similar in
|
117
|
+
# some ways to the Oj::Bag class or the Oj::EasyHash class.
|
118
|
+
class GenericObject < OpenStruct
|
119
|
+
class << self
|
120
|
+
alias [] new
|
121
|
+
|
122
|
+
def json_creatable?
|
123
|
+
@json_creatable
|
124
|
+
end
|
125
|
+
|
126
|
+
attr_writer :json_creatable
|
127
|
+
|
128
|
+
def json_create(data)
|
129
|
+
data = data.dup
|
130
|
+
data.delete JSON.create_id
|
131
|
+
self[data]
|
132
|
+
end
|
133
|
+
|
134
|
+
def from_hash(object)
|
135
|
+
case
|
136
|
+
when object.respond_to?(:to_hash)
|
137
|
+
result = new
|
138
|
+
object.to_hash.each do |key, value|
|
139
|
+
result[key] = from_hash(value)
|
140
|
+
end
|
141
|
+
result
|
142
|
+
when object.respond_to?(:to_ary)
|
143
|
+
object.to_ary.map { |a| from_hash(a) }
|
144
|
+
else
|
145
|
+
object
|
131
146
|
end
|
132
|
-
result
|
133
|
-
when object.respond_to?(:to_ary)
|
134
|
-
object.to_ary.map { |a| from_hash(a) }
|
135
|
-
else
|
136
|
-
object
|
137
147
|
end
|
138
|
-
end
|
139
148
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
149
|
+
def load(source, proc = nil, opts = {})
|
150
|
+
result = ::JSON.load(source, proc, opts.merge(:object_class => self))
|
151
|
+
result.nil? ? new : result
|
152
|
+
end
|
144
153
|
|
145
|
-
|
146
|
-
|
147
|
-
|
154
|
+
def dump(obj, *args)
|
155
|
+
::JSON.dump(obj, *args)
|
156
|
+
end
|
148
157
|
|
149
|
-
|
158
|
+
end # self
|
150
159
|
|
151
|
-
|
160
|
+
self.json_creatable = false
|
152
161
|
|
153
|
-
|
154
|
-
|
155
|
-
|
162
|
+
def to_hash
|
163
|
+
table
|
164
|
+
end
|
156
165
|
|
157
|
-
|
158
|
-
|
159
|
-
|
166
|
+
def [](name)
|
167
|
+
__send__(name)
|
168
|
+
end unless method_defined?(:[])
|
160
169
|
|
161
|
-
|
162
|
-
|
163
|
-
|
170
|
+
def []=(name, value)
|
171
|
+
__send__("#{name}=", value)
|
172
|
+
end unless method_defined?(:[]=)
|
164
173
|
|
165
|
-
|
166
|
-
|
167
|
-
|
174
|
+
def |(other)
|
175
|
+
self.class[other.to_hash.merge(to_hash)]
|
176
|
+
end
|
168
177
|
|
169
|
-
|
170
|
-
|
171
|
-
|
178
|
+
def as_json(*)
|
179
|
+
{ JSON.create_id => self.class.name }.merge to_hash
|
180
|
+
end
|
172
181
|
|
173
|
-
|
174
|
-
|
182
|
+
def to_json(*a)
|
183
|
+
as_json.to_json(*a)
|
184
|
+
end
|
175
185
|
end
|
176
|
-
|
177
|
-
|
178
|
-
end
|
186
|
+
|
187
|
+
end # JSON
|
188
|
+
end
|
data/lib/oj/mimic.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
1
3
|
require 'bigdecimal'
|
2
4
|
begin
|
3
5
|
require 'ostruct'
|
@@ -266,7 +268,7 @@ module Oj
|
|
266
268
|
end
|
267
269
|
end
|
268
270
|
def self.json_create(h)
|
269
|
-
if usec = h.delete('u')
|
271
|
+
if (usec = h.delete('u'))
|
270
272
|
h['n'] = usec * 1000
|
271
273
|
end
|
272
274
|
if instance_methods.include?(:tv_nsec)
|
data/lib/oj/version.rb
CHANGED
data/test/foo.rb
CHANGED
@@ -5,11 +5,10 @@ $LOAD_PATH << '.'
|
|
5
5
|
$LOAD_PATH << File.join(__dir__, '../lib')
|
6
6
|
$LOAD_PATH << File.join(__dir__, '../ext')
|
7
7
|
|
8
|
+
require 'json'
|
8
9
|
require 'oj'
|
9
|
-
|
10
|
-
GC.stress = true
|
10
|
+
require 'oj/json'
|
11
11
|
|
12
12
|
Oj.mimic_JSON
|
13
13
|
|
14
|
-
|
15
|
-
pp JSON('{ "a": 1, "b": 2 }', :object_class => JSON::GenericObject)
|
14
|
+
JSON.parse("[]")
|
@@ -128,8 +128,10 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
|
|
128
128
|
too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
|
129
129
|
assert_equal too_deep, JSON.dump(eval(too_deep))
|
130
130
|
assert_kind_of String, Marshal.dump(eval(too_deep))
|
131
|
-
|
132
|
-
|
131
|
+
if RUBY_ENGINE != 'truffleruby'
|
132
|
+
assert_raise(ArgumentError) { JSON.dump(eval(too_deep), 100) }
|
133
|
+
assert_raise(ArgumentError) { Marshal.dump(eval(too_deep), 100) }
|
134
|
+
end
|
133
135
|
assert_equal too_deep, JSON.dump(eval(too_deep), 101)
|
134
136
|
assert_kind_of String, Marshal.dump(eval(too_deep), 101)
|
135
137
|
output = StringIO.new
|