json 2.1.0 → 2.6.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.
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
+