json 2.1.0 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES.md +63 -5
  3. data/LICENSE +56 -0
  4. data/README.md +56 -23
  5. data/VERSION +1 -1
  6. data/ext/json/ext/generator/generator.c +223 -58
  7. data/ext/json/ext/generator/generator.h +5 -2
  8. data/ext/json/ext/parser/extconf.rb +26 -0
  9. data/ext/json/ext/parser/parser.c +2973 -1744
  10. data/ext/json/ext/parser/parser.h +6 -1
  11. data/ext/json/ext/parser/parser.rl +130 -22
  12. data/ext/json/extconf.rb +1 -0
  13. data/json.gemspec +0 -0
  14. data/lib/json/add/bigdecimal.rb +2 -2
  15. data/lib/json/add/complex.rb +2 -3
  16. data/lib/json/add/ostruct.rb +1 -1
  17. data/lib/json/add/rational.rb +2 -3
  18. data/lib/json/add/regexp.rb +2 -2
  19. data/lib/json/add/set.rb +29 -0
  20. data/lib/json/common.rb +372 -125
  21. data/lib/json/pure/generator.rb +31 -10
  22. data/lib/json/pure/parser.rb +32 -6
  23. data/lib/json/version.rb +1 -1
  24. data/lib/json.rb +549 -29
  25. metadata +19 -113
  26. data/.gitignore +0 -17
  27. data/.travis.yml +0 -19
  28. data/Gemfile +0 -16
  29. data/README-json-jruby.md +0 -33
  30. data/Rakefile +0 -408
  31. data/data/example.json +0 -1
  32. data/data/index.html +0 -38
  33. data/data/prototype.js +0 -4184
  34. data/diagrams/.keep +0 -0
  35. data/install.rb +0 -23
  36. data/java/src/json/ext/ByteListTranscoder.java +0 -166
  37. data/java/src/json/ext/Generator.java +0 -443
  38. data/java/src/json/ext/GeneratorMethods.java +0 -231
  39. data/java/src/json/ext/GeneratorService.java +0 -42
  40. data/java/src/json/ext/GeneratorState.java +0 -490
  41. data/java/src/json/ext/OptionsReader.java +0 -113
  42. data/java/src/json/ext/Parser.java +0 -2362
  43. data/java/src/json/ext/Parser.rl +0 -893
  44. data/java/src/json/ext/ParserService.java +0 -34
  45. data/java/src/json/ext/RuntimeInfo.java +0 -116
  46. data/java/src/json/ext/StringDecoder.java +0 -166
  47. data/java/src/json/ext/StringEncoder.java +0 -111
  48. data/java/src/json/ext/Utils.java +0 -88
  49. data/json-java.gemspec +0 -38
  50. data/json_pure.gemspec +0 -38
  51. data/lib/json/ext/.keep +0 -0
  52. data/references/rfc7159.txt +0 -899
  53. data/tests/fixtures/fail10.json +0 -1
  54. data/tests/fixtures/fail11.json +0 -1
  55. data/tests/fixtures/fail12.json +0 -1
  56. data/tests/fixtures/fail13.json +0 -1
  57. data/tests/fixtures/fail14.json +0 -1
  58. data/tests/fixtures/fail18.json +0 -1
  59. data/tests/fixtures/fail19.json +0 -1
  60. data/tests/fixtures/fail2.json +0 -1
  61. data/tests/fixtures/fail20.json +0 -1
  62. data/tests/fixtures/fail21.json +0 -1
  63. data/tests/fixtures/fail22.json +0 -1
  64. data/tests/fixtures/fail23.json +0 -1
  65. data/tests/fixtures/fail24.json +0 -1
  66. data/tests/fixtures/fail25.json +0 -1
  67. data/tests/fixtures/fail27.json +0 -2
  68. data/tests/fixtures/fail28.json +0 -2
  69. data/tests/fixtures/fail3.json +0 -1
  70. data/tests/fixtures/fail4.json +0 -1
  71. data/tests/fixtures/fail5.json +0 -1
  72. data/tests/fixtures/fail6.json +0 -1
  73. data/tests/fixtures/fail7.json +0 -1
  74. data/tests/fixtures/fail8.json +0 -1
  75. data/tests/fixtures/fail9.json +0 -1
  76. data/tests/fixtures/obsolete_fail1.json +0 -1
  77. data/tests/fixtures/pass1.json +0 -56
  78. data/tests/fixtures/pass15.json +0 -1
  79. data/tests/fixtures/pass16.json +0 -1
  80. data/tests/fixtures/pass17.json +0 -1
  81. data/tests/fixtures/pass2.json +0 -1
  82. data/tests/fixtures/pass26.json +0 -1
  83. data/tests/fixtures/pass3.json +0 -6
  84. data/tests/json_addition_test.rb +0 -193
  85. data/tests/json_common_interface_test.rb +0 -126
  86. data/tests/json_encoding_test.rb +0 -107
  87. data/tests/json_ext_parser_test.rb +0 -15
  88. data/tests/json_fixtures_test.rb +0 -32
  89. data/tests/json_generator_test.rb +0 -377
  90. data/tests/json_generic_object_test.rb +0 -82
  91. data/tests/json_parser_test.rb +0 -471
  92. data/tests/json_string_matching_test.rb +0 -38
  93. data/tests/test_helper.rb +0 -21
  94. data/tools/diff.sh +0 -18
  95. data/tools/fuzz.rb +0 -131
  96. data/tools/server.rb +0 -62
@@ -13,6 +13,10 @@
13
13
  #include "st.h"
14
14
  #endif
15
15
 
16
+ #ifndef MAYBE_UNUSED
17
+ # define MAYBE_UNUSED(x) x
18
+ #endif
19
+
16
20
  #define option_given_p(opts, key) RTEST(rb_funcall(opts, i_key_p, 1, key))
17
21
 
18
22
  /* unicode */
@@ -37,6 +41,7 @@ typedef struct JSON_ParserStruct {
37
41
  int allow_nan;
38
42
  int parsing_name;
39
43
  int symbolize_names;
44
+ int freeze;
40
45
  VALUE object_class;
41
46
  VALUE array_class;
42
47
  VALUE decimal_class;
@@ -62,7 +67,7 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
62
67
  static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result);
63
68
  static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result);
64
69
  static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
65
- static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd);
70
+ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize);
66
71
  static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result);
67
72
  static VALUE convert_encoding(VALUE source);
68
73
  static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self);
@@ -25,7 +25,7 @@ enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
25
25
 
26
26
  /* unicode */
27
27
 
28
- static const char digit_values[256] = {
28
+ static const signed char digit_values[256] = {
29
29
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
30
30
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
31
31
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1,
@@ -44,7 +44,7 @@ static const char digit_values[256] = {
44
44
 
45
45
  static UTF32 unescape_unicode(const unsigned char *p)
46
46
  {
47
- char b;
47
+ signed char b;
48
48
  UTF32 result = 0;
49
49
  b = digit_values[p[0]];
50
50
  if (b < 0) return UNI_REPLACEMENT_CHAR;
@@ -94,7 +94,7 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
94
94
  i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
95
95
  i_object_class, i_array_class, i_decimal_class, i_key_p,
96
96
  i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
97
- i_leftshift, i_new;
97
+ i_leftshift, i_new, i_try_convert, i_freeze, i_uminus;
98
98
 
99
99
  %%{
100
100
  machine JSON_common;
@@ -137,6 +137,7 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
137
137
  fhold; fbreak;
138
138
  } else {
139
139
  if (NIL_P(json->object_class)) {
140
+ OBJ_FREEZE(last_name);
140
141
  rb_hash_aset(*result, last_name, v);
141
142
  } else {
142
143
  rb_funcall(*result, i_aset, 2, last_name, v);
@@ -288,6 +289,10 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
288
289
  %% write init;
289
290
  %% write exec;
290
291
 
292
+ if (json->freeze) {
293
+ OBJ_FREEZE(*result);
294
+ }
295
+
291
296
  if (cs >= JSON_value_first_final) {
292
297
  return p;
293
298
  } else {
@@ -348,17 +353,46 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
348
353
  %% write exec;
349
354
 
350
355
  if (cs >= JSON_float_first_final) {
356
+ VALUE mod = Qnil;
357
+ ID method_id = 0;
358
+ if (rb_respond_to(json->decimal_class, i_try_convert)) {
359
+ mod = json->decimal_class;
360
+ method_id = i_try_convert;
361
+ } else if (rb_respond_to(json->decimal_class, i_new)) {
362
+ mod = json->decimal_class;
363
+ method_id = i_new;
364
+ } else if (RB_TYPE_P(json->decimal_class, T_CLASS)) {
365
+ VALUE name = rb_class_name(json->decimal_class);
366
+ const char *name_cstr = RSTRING_PTR(name);
367
+ const char *last_colon = strrchr(name_cstr, ':');
368
+ if (last_colon) {
369
+ const char *mod_path_end = last_colon - 1;
370
+ VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr);
371
+ mod = rb_path_to_class(mod_path);
372
+
373
+ const char *method_name_beg = last_colon + 1;
374
+ long before_len = method_name_beg - name_cstr;
375
+ long len = RSTRING_LEN(name) - before_len;
376
+ VALUE method_name = rb_str_substr(name, before_len, len);
377
+ method_id = SYM2ID(rb_str_intern(method_name));
378
+ } else {
379
+ mod = rb_mKernel;
380
+ method_id = SYM2ID(rb_str_intern(name));
381
+ }
382
+ }
383
+
351
384
  long len = p - json->memo;
352
385
  fbuffer_clear(json->fbuffer);
353
386
  fbuffer_append(json->fbuffer, json->memo, len);
354
387
  fbuffer_append_char(json->fbuffer, '\0');
355
- if (NIL_P(json->decimal_class)) {
356
- *result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
388
+
389
+ if (method_id) {
390
+ VALUE text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
391
+ *result = rb_funcallv(mod, method_id, 1, &text);
357
392
  } else {
358
- VALUE text;
359
- text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
360
- *result = rb_funcall(json->decimal_class, i_new, 1, text);
393
+ *result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
361
394
  }
395
+
362
396
  return p + 1;
363
397
  } else {
364
398
  return NULL;
@@ -418,17 +452,29 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
418
452
  }
419
453
  }
420
454
 
421
- static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
455
+ static const size_t MAX_STACK_BUFFER_SIZE = 128;
456
+ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize)
422
457
  {
423
- char *p = string, *pe = string, *unescape;
458
+ VALUE result = Qnil;
459
+ size_t bufferSize = stringEnd - string;
460
+ char *p = string, *pe = string, *unescape, *bufferStart, *buffer;
424
461
  int unescape_len;
425
462
  char buf[4];
426
463
 
464
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
465
+ bufferStart = buffer = ALLOC_N(char, bufferSize);
466
+ } else {
467
+ bufferStart = buffer = ALLOCA_N(char, bufferSize);
468
+ }
469
+
427
470
  while (pe < stringEnd) {
428
471
  if (*pe == '\\') {
429
472
  unescape = (char *) "?";
430
473
  unescape_len = 1;
431
- if (pe > p) rb_str_buf_cat(result, p, pe - p);
474
+ if (pe > p) {
475
+ MEMCPY(buffer, p, char, pe - p);
476
+ buffer += pe - p;
477
+ }
432
478
  switch (*++pe) {
433
479
  case 'n':
434
480
  unescape = (char *) "\n";
@@ -453,6 +499,9 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
453
499
  break;
454
500
  case 'u':
455
501
  if (pe > stringEnd - 4) {
502
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
503
+ free(bufferStart);
504
+ }
456
505
  rb_enc_raise(
457
506
  EXC_ENCODING eParserError,
458
507
  "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
@@ -463,6 +512,9 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
463
512
  if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
464
513
  pe++;
465
514
  if (pe > stringEnd - 6) {
515
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
516
+ free(bufferStart);
517
+ }
466
518
  rb_enc_raise(
467
519
  EXC_ENCODING eParserError,
468
520
  "%u: incomplete surrogate pair at '%s'", __LINE__, p
@@ -486,13 +538,55 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
486
538
  p = pe;
487
539
  continue;
488
540
  }
489
- rb_str_buf_cat(result, unescape, unescape_len);
541
+ MEMCPY(buffer, unescape, char, unescape_len);
542
+ buffer += unescape_len;
490
543
  p = ++pe;
491
544
  } else {
492
545
  pe++;
493
546
  }
494
547
  }
495
- rb_str_buf_cat(result, p, pe - p);
548
+
549
+ if (pe > p) {
550
+ MEMCPY(buffer, p, char, pe - p);
551
+ buffer += pe - p;
552
+ }
553
+
554
+ # ifdef HAVE_RB_ENC_INTERNED_STR
555
+ if (intern) {
556
+ result = rb_enc_interned_str(bufferStart, (long)(buffer - bufferStart), rb_utf8_encoding());
557
+ } else {
558
+ result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
559
+ }
560
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
561
+ free(bufferStart);
562
+ }
563
+ # else
564
+ result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
565
+
566
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
567
+ free(bufferStart);
568
+ }
569
+
570
+ if (intern) {
571
+ # if STR_UMINUS_DEDUPE_FROZEN
572
+ // Starting from MRI 2.8 it is preferable to freeze the string
573
+ // before deduplication so that it can be interned directly
574
+ // otherwise it would be duplicated first which is wasteful.
575
+ result = rb_funcall(rb_str_freeze(result), i_uminus, 0);
576
+ # elif STR_UMINUS_DEDUPE
577
+ // MRI 2.5 and older do not deduplicate strings that are already
578
+ // frozen.
579
+ result = rb_funcall(result, i_uminus, 0);
580
+ # else
581
+ result = rb_str_freeze(result);
582
+ # endif
583
+ }
584
+ # endif
585
+
586
+ if (symbolize) {
587
+ result = rb_str_intern(result);
588
+ }
589
+
496
590
  return result;
497
591
  }
498
592
 
@@ -503,12 +597,11 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
503
597
  write data;
504
598
 
505
599
  action parse_string {
506
- *result = json_string_unescape(*result, json->memo + 1, p);
600
+ *result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names);
507
601
  if (NIL_P(*result)) {
508
602
  fhold;
509
603
  fbreak;
510
604
  } else {
511
- FORCE_UTF8(*result);
512
605
  fexec p + 1;
513
606
  }
514
607
  }
@@ -535,7 +628,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
535
628
  int cs = EVIL;
536
629
  VALUE match_string;
537
630
 
538
- *result = rb_str_buf_new(0);
539
631
  %% write init;
540
632
  json->memo = p;
541
633
  %% write exec;
@@ -551,11 +643,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
551
643
  }
552
644
  }
553
645
 
554
- if (json->symbolize_names && json->parsing_name) {
555
- *result = rb_str_intern(*result);
556
- } else {
557
- rb_str_resize(*result, RSTRING_LEN(*result));
558
- }
559
646
  if (cs >= JSON_string_first_final) {
560
647
  return p + 1;
561
648
  } else {
@@ -662,6 +749,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
662
749
  } else {
663
750
  json->symbolize_names = 0;
664
751
  }
752
+ tmp = ID2SYM(i_freeze);
753
+ if (option_given_p(opts, tmp)) {
754
+ json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
755
+ } else {
756
+ json->freeze = 0;
757
+ }
665
758
  tmp = ID2SYM(i_create_additions);
666
759
  if (option_given_p(opts, tmp)) {
667
760
  json->create_additions = RTEST(rb_hash_aref(opts, tmp));
@@ -710,7 +803,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
710
803
  } else {
711
804
  json->max_nesting = 100;
712
805
  json->allow_nan = 0;
713
- json->create_additions = 1;
806
+ json->create_additions = 0;
714
807
  json->create_id = rb_funcall(mJSON, i_create_id, 0);
715
808
  json->object_class = Qnil;
716
809
  json->array_class = Qnil;
@@ -824,20 +917,32 @@ static VALUE cParser_source(VALUE self)
824
917
 
825
918
  void Init_parser(void)
826
919
  {
920
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
921
+ rb_ext_ractor_safe(true);
922
+ #endif
923
+
924
+ #undef rb_intern
827
925
  rb_require("json/common");
828
926
  mJSON = rb_define_module("JSON");
829
927
  mExt = rb_define_module_under(mJSON, "Ext");
830
928
  cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
831
929
  eParserError = rb_path2class("JSON::ParserError");
832
930
  eNestingError = rb_path2class("JSON::NestingError");
931
+ rb_gc_register_mark_object(eParserError);
932
+ rb_gc_register_mark_object(eNestingError);
833
933
  rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
834
934
  rb_define_method(cParser, "initialize", cParser_initialize, -1);
835
935
  rb_define_method(cParser, "parse", cParser_parse, 0);
836
936
  rb_define_method(cParser, "source", cParser_source, 0);
837
937
 
838
938
  CNaN = rb_const_get(mJSON, rb_intern("NaN"));
939
+ rb_gc_register_mark_object(CNaN);
940
+
839
941
  CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
942
+ rb_gc_register_mark_object(CInfinity);
943
+
840
944
  CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
945
+ rb_gc_register_mark_object(CMinusInfinity);
841
946
 
842
947
  i_json_creatable_p = rb_intern("json_creatable?");
843
948
  i_json_create = rb_intern("json_create");
@@ -858,6 +963,9 @@ void Init_parser(void)
858
963
  i_aref = rb_intern("[]");
859
964
  i_leftshift = rb_intern("<<");
860
965
  i_new = rb_intern("new");
966
+ i_try_convert = rb_intern("try_convert");
967
+ i_freeze = rb_intern("freeze");
968
+ i_uminus = rb_intern("-@");
861
969
  }
862
970
 
863
971
  /*
data/ext/json/extconf.rb CHANGED
@@ -1,2 +1,3 @@
1
1
  require 'mkmf'
2
+
2
3
  create_makefile('json')
data/json.gemspec CHANGED
Binary file
@@ -23,7 +23,7 @@ class BigDecimal
23
23
  end
24
24
 
25
25
  # return the JSON value
26
- def to_json(*)
27
- as_json.to_json
26
+ def to_json(*args)
27
+ as_json.to_json(*args)
28
28
  end
29
29
  end
@@ -2,7 +2,6 @@
2
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
3
  require 'json'
4
4
  end
5
- defined?(::Complex) or require 'complex'
6
5
 
7
6
  class Complex
8
7
 
@@ -23,7 +22,7 @@ class Complex
23
22
  end
24
23
 
25
24
  # Stores class name (Complex) along with real value <tt>r</tt> and imaginary value <tt>i</tt> as JSON string
26
- def to_json(*)
27
- as_json.to_json
25
+ def to_json(*args)
26
+ as_json.to_json(*args)
28
27
  end
29
28
  end
@@ -23,7 +23,7 @@ class OpenStruct
23
23
  }
24
24
  end
25
25
 
26
- # Stores class name (OpenStruct) with this struct's values <tt>v</tt> as a
26
+ # Stores class name (OpenStruct) with this struct's values <tt>t</tt> as a
27
27
  # JSON string.
28
28
  def to_json(*args)
29
29
  as_json.to_json(*args)
@@ -2,7 +2,6 @@
2
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
3
  require 'json'
4
4
  end
5
- defined?(::Rational) or require 'rational'
6
5
 
7
6
  class Rational
8
7
  # Deserializes JSON string by converting numerator value <tt>n</tt>,
@@ -22,7 +21,7 @@ class Rational
22
21
  end
23
22
 
24
23
  # Stores class name (Rational) along with numerator value <tt>n</tt> and denominator value <tt>d</tt> as JSON string
25
- def to_json(*)
26
- as_json.to_json
24
+ def to_json(*args)
25
+ as_json.to_json(*args)
27
26
  end
28
27
  end
@@ -24,7 +24,7 @@ class Regexp
24
24
 
25
25
  # Stores class name (Regexp) with options <tt>o</tt> and source <tt>s</tt>
26
26
  # (Regexp or String) as JSON string
27
- def to_json(*)
28
- as_json.to_json
27
+ def to_json(*args)
28
+ as_json.to_json(*args)
29
29
  end
30
30
  end
@@ -0,0 +1,29 @@
1
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
2
+ require 'json'
3
+ end
4
+ defined?(::Set) or require 'set'
5
+
6
+ class Set
7
+ # Import a JSON Marshalled object.
8
+ #
9
+ # method used for JSON marshalling support.
10
+ def self.json_create(object)
11
+ new object['a']
12
+ end
13
+
14
+ # Marshal the object to JSON.
15
+ #
16
+ # method used for JSON marshalling support.
17
+ def as_json(*)
18
+ {
19
+ JSON.create_id => self.class.name,
20
+ 'a' => to_a,
21
+ }
22
+ end
23
+
24
+ # return the JSON value
25
+ def to_json(*args)
26
+ as_json.to_json(*args)
27
+ end
28
+ end
29
+