oj 3.9.2 → 3.10.18
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/README.md +2 -2
 - data/ext/oj/buf.h +2 -30
 - data/ext/oj/cache8.h +1 -29
 - data/ext/oj/circarray.c +4 -8
 - data/ext/oj/circarray.h +1 -4
 - data/ext/oj/code.c +3 -6
 - data/ext/oj/code.h +1 -4
 - data/ext/oj/compat.c +6 -9
 - data/ext/oj/custom.c +8 -7
 - data/ext/oj/dump.c +33 -26
 - data/ext/oj/dump.h +1 -4
 - data/ext/oj/dump_compat.c +9 -14
 - data/ext/oj/dump_leaf.c +2 -5
 - data/ext/oj/dump_object.c +19 -15
 - data/ext/oj/dump_strict.c +7 -9
 - data/ext/oj/encode.h +1 -29
 - data/ext/oj/err.c +1 -4
 - data/ext/oj/err.h +1 -29
 - data/ext/oj/extconf.rb +5 -0
 - data/ext/oj/fast.c +14 -42
 - data/ext/oj/hash.c +4 -32
 - data/ext/oj/hash.h +1 -29
 - data/ext/oj/hash_test.c +1 -29
 - data/ext/oj/mimic_json.c +28 -10
 - data/ext/oj/object.c +4 -6
 - data/ext/oj/odd.c +1 -4
 - data/ext/oj/odd.h +1 -4
 - data/ext/oj/oj.c +74 -38
 - data/ext/oj/oj.h +9 -7
 - data/ext/oj/parse.c +127 -52
 - data/ext/oj/parse.h +4 -5
 - data/ext/oj/rails.c +38 -8
 - data/ext/oj/rails.h +1 -4
 - data/ext/oj/reader.c +5 -8
 - data/ext/oj/reader.h +2 -5
 - data/ext/oj/resolve.c +1 -4
 - data/ext/oj/resolve.h +1 -4
 - data/ext/oj/rxclass.c +3 -6
 - data/ext/oj/rxclass.h +1 -4
 - data/ext/oj/saj.c +6 -9
 - data/ext/oj/scp.c +1 -4
 - data/ext/oj/sparse.c +31 -26
 - data/ext/oj/stream_writer.c +4 -9
 - data/ext/oj/strict.c +3 -6
 - data/ext/oj/string_writer.c +1 -4
 - data/ext/oj/trace.c +5 -8
 - data/ext/oj/trace.h +1 -4
 - data/ext/oj/util.c +1 -1
 - data/ext/oj/util.h +1 -1
 - data/ext/oj/val_stack.c +1 -29
 - data/ext/oj/val_stack.h +1 -29
 - data/ext/oj/wab.c +10 -13
 - data/lib/oj/mimic.rb +45 -1
 - data/lib/oj/version.rb +1 -1
 - data/lib/oj.rb +0 -8
 - data/pages/Modes.md +1 -1
 - data/pages/Options.md +15 -11
 - data/pages/Rails.md +60 -21
 - data/test/activesupport5/abstract_unit.rb +45 -0
 - data/test/activesupport5/decoding_test.rb +68 -60
 - data/test/activesupport5/encoding_test.rb +111 -96
 - data/test/activesupport5/encoding_test_cases.rb +33 -25
 - data/test/activesupport5/test_helper.rb +43 -21
 - data/test/activesupport5/time_zone_test_helpers.rb +18 -3
 - data/test/activesupport6/abstract_unit.rb +44 -0
 - data/test/activesupport6/decoding_test.rb +133 -0
 - data/test/activesupport6/encoding_test.rb +507 -0
 - data/test/activesupport6/encoding_test_cases.rb +98 -0
 - data/test/activesupport6/test_common.rb +17 -0
 - data/test/activesupport6/test_helper.rb +163 -0
 - data/test/activesupport6/time_zone_test_helpers.rb +39 -0
 - data/test/bar.rb +21 -11
 - data/test/baz.rb +16 -0
 - data/test/foo.rb +39 -8
 - data/test/json_gem/json_common_interface_test.rb +8 -3
 - data/test/prec.rb +23 -0
 - data/test/sample_json.rb +1 -1
 - data/test/test_compat.rb +14 -8
 - data/test/test_custom.rb +36 -6
 - data/test/test_integer_range.rb +1 -2
 - data/test/test_object.rb +12 -3
 - data/test/test_rails.rb +35 -0
 - data/test/test_strict.rb +24 -1
 - data/test/test_various.rb +42 -64
 - data/test/tests.rb +1 -0
 - metadata +29 -7
 
    
        data/ext/oj/wab.c
    CHANGED
    
    | 
         @@ -1,7 +1,4 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
             * Copyright (c) 2012, Peter Ohler
         
     | 
| 
       3 
     | 
    
         
            -
             * All rights reserved.
         
     | 
| 
       4 
     | 
    
         
            -
             */
         
     | 
| 
      
 1 
     | 
    
         
            +
            // Copyright (c) 2012 Peter Ohler. All rights reserved.
         
     | 
| 
       5 
2 
     | 
    
         | 
| 
       6 
3 
     | 
    
         
             
            #include <stdlib.h>
         
     | 
| 
       7 
4 
     | 
    
         
             
            #include <stdio.h>
         
     | 
| 
         @@ -148,11 +145,12 @@ dump_array(VALUE a, int depth, Out out, bool as_ok) { 
     | 
|
| 
       148 
145 
     | 
    
         
             
            }
         
     | 
| 
       149 
146 
     | 
    
         | 
| 
       150 
147 
     | 
    
         
             
            static int
         
     | 
| 
       151 
     | 
    
         
            -
            hash_cb(VALUE key, VALUE value,  
     | 
| 
      
 148 
     | 
    
         
            +
            hash_cb(VALUE key, VALUE value, VALUE ov) {
         
     | 
| 
      
 149 
     | 
    
         
            +
                Out		out = (Out)ov;
         
     | 
| 
       152 
150 
     | 
    
         
             
                int		depth = out->depth;
         
     | 
| 
       153 
151 
     | 
    
         
             
                long	size;
         
     | 
| 
       154 
152 
     | 
    
         
             
                int		rtype = rb_type(key);
         
     | 
| 
       155 
     | 
    
         
            -
             
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
       156 
154 
     | 
    
         
             
                if (rtype != T_SYMBOL) {
         
     | 
| 
       157 
155 
     | 
    
         
             
            	rb_raise(rb_eTypeError, "In :wab mode all Hash keys must be Symbols, not %s.\n", rb_class2name(rb_obj_class(key)));
         
     | 
| 
       158 
156 
     | 
    
         
             
                }
         
     | 
| 
         @@ -270,7 +268,7 @@ static DumpFunc	wab_funcs[] = { 
     | 
|
| 
       270 
268 
     | 
    
         
             
            void
         
     | 
| 
       271 
269 
     | 
    
         
             
            oj_dump_wab_val(VALUE obj, int depth, Out out) {
         
     | 
| 
       272 
270 
     | 
    
         
             
                int	type = rb_type(obj);
         
     | 
| 
       273 
     | 
    
         
            -
             
     | 
| 
      
 271 
     | 
    
         
            +
             
     | 
| 
       274 
272 
     | 
    
         
             
                if (Yes == out->opts->trace) {
         
     | 
| 
       275 
273 
     | 
    
         
             
            	oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
         
     | 
| 
       276 
274 
     | 
    
         
             
                }
         
     | 
| 
         @@ -324,7 +322,7 @@ add_value(ParseInfo pi, VALUE val) { 
     | 
|
| 
       324 
322 
     | 
    
         
             
            static bool
         
     | 
| 
       325 
323 
     | 
    
         
             
            uuid_check(const char *str, int len) {
         
     | 
| 
       326 
324 
     | 
    
         
             
                int		i;
         
     | 
| 
       327 
     | 
    
         
            -
             
     | 
| 
      
 325 
     | 
    
         
            +
             
     | 
| 
       328 
326 
     | 
    
         
             
                for (i = 0; i < 8; i++, str++) {
         
     | 
| 
       329 
327 
     | 
    
         
             
            	if ('x' != hex_chars[*(uint8_t*)str]) {
         
     | 
| 
       330 
328 
     | 
    
         
             
            	    return false;
         
     | 
| 
         @@ -380,7 +378,7 @@ time_parse(const char *s, int len) { 
     | 
|
| 
       380 
378 
     | 
    
         
             
                long	nsecs = 0;
         
     | 
| 
       381 
379 
     | 
    
         
             
                int		i;
         
     | 
| 
       382 
380 
     | 
    
         
             
                time_t	secs;
         
     | 
| 
       383 
     | 
    
         
            -
             
     | 
| 
      
 381 
     | 
    
         
            +
             
     | 
| 
       384 
382 
     | 
    
         
             
                memset(&tm, 0, sizeof(tm));
         
     | 
| 
       385 
383 
     | 
    
         
             
                if ('-' == *s) {
         
     | 
| 
       386 
384 
     | 
    
         
             
            	s++;
         
     | 
| 
         @@ -444,7 +442,7 @@ protect_uri(VALUE rstr) { 
     | 
|
| 
       444 
442 
     | 
    
         
             
            static VALUE
         
     | 
| 
       445 
443 
     | 
    
         
             
            cstr_to_rstr(const char *str, size_t len) {
         
     | 
| 
       446 
444 
     | 
    
         
             
                volatile VALUE	v = Qnil;
         
     | 
| 
       447 
     | 
    
         
            -
             
     | 
| 
      
 445 
     | 
    
         
            +
             
     | 
| 
       448 
446 
     | 
    
         
             
                if (30 == len && '-' == str[4] && '-' == str[7] && 'T' == str[10] && ':' == str[13] && ':' == str[16]  && '.' == str[19] && 'Z' == str[29]) {
         
     | 
| 
       449 
447 
     | 
    
         
             
            	if (Qnil != (v = time_parse(str, (int)len))) {
         
     | 
| 
       450 
448 
     | 
    
         
             
            	    return v;
         
     | 
| 
         @@ -521,7 +519,7 @@ hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char 
     | 
|
| 
       521 
519 
     | 
    
         
             
            static void
         
     | 
| 
       522 
520 
     | 
    
         
             
            hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
         
     | 
| 
       523 
521 
     | 
    
         
             
                volatile VALUE	rval = Qnil;
         
     | 
| 
       524 
     | 
    
         
            -
             
     | 
| 
      
 522 
     | 
    
         
            +
             
     | 
| 
       525 
523 
     | 
    
         
             
                if (ni->infinity || ni->nan) {
         
     | 
| 
       526 
524 
     | 
    
         
             
            	oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
         
     | 
| 
       527 
525 
     | 
    
         
             
                }
         
     | 
| 
         @@ -551,7 +549,7 @@ start_array(ParseInfo pi) { 
     | 
|
| 
       551 
549 
     | 
    
         
             
            static void
         
     | 
| 
       552 
550 
     | 
    
         
             
            array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
         
     | 
| 
       553 
551 
     | 
    
         
             
                volatile VALUE	rval = cstr_to_rstr(str, len);
         
     | 
| 
       554 
     | 
    
         
            -
             
     | 
| 
      
 552 
     | 
    
         
            +
             
     | 
| 
       555 
553 
     | 
    
         
             
                rb_ary_push(stack_peek(&pi->stack)->val, rval);
         
     | 
| 
       556 
554 
     | 
    
         
             
                if (Yes == pi->options.trace) {
         
     | 
| 
       557 
555 
     | 
    
         
             
            	oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, rval);
         
     | 
| 
         @@ -628,4 +626,3 @@ oj_wab_parse_cstr(int argc, VALUE *argv, char *json, size_t len) { 
     | 
|
| 
       628 
626 
     | 
    
         | 
| 
       629 
627 
     | 
    
         
             
                return oj_pi_parse(argc, argv, &pi, json, len, true);
         
     | 
| 
       630 
628 
     | 
    
         
             
            }
         
     | 
| 
       631 
     | 
    
         
            -
             
     | 
    
        data/lib/oj/mimic.rb
    CHANGED
    
    | 
         @@ -8,6 +8,50 @@ end 
     | 
|
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
            module Oj
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
      
 11 
     | 
    
         
            +
              ##
         
     | 
| 
      
 12 
     | 
    
         
            +
              # Custom mode can be used to emulate the compat mode with some minor
         
     | 
| 
      
 13 
     | 
    
         
            +
              # differences. These are the options that setup the custom mode to be like
         
     | 
| 
      
 14 
     | 
    
         
            +
              # the compat mode.
         
     | 
| 
      
 15 
     | 
    
         
            +
              CUSTOM_MIMIC_JSON_OPTIONS = {
         
     | 
| 
      
 16 
     | 
    
         
            +
                allow_gc: true,
         
     | 
| 
      
 17 
     | 
    
         
            +
                allow_invalid_unicode: false,
         
     | 
| 
      
 18 
     | 
    
         
            +
                allow_nan: false,
         
     | 
| 
      
 19 
     | 
    
         
            +
                array_class: nil,
         
     | 
| 
      
 20 
     | 
    
         
            +
                array_nl: nil,
         
     | 
| 
      
 21 
     | 
    
         
            +
                auto_define: false,
         
     | 
| 
      
 22 
     | 
    
         
            +
                bigdecimal_as_decimal: false,
         
     | 
| 
      
 23 
     | 
    
         
            +
                bigdecimal_load: :auto,
         
     | 
| 
      
 24 
     | 
    
         
            +
                circular: false,
         
     | 
| 
      
 25 
     | 
    
         
            +
                class_cache: false,
         
     | 
| 
      
 26 
     | 
    
         
            +
                create_additions: false,
         
     | 
| 
      
 27 
     | 
    
         
            +
                create_id: "json_class",
         
     | 
| 
      
 28 
     | 
    
         
            +
                empty_string: false,
         
     | 
| 
      
 29 
     | 
    
         
            +
                escape_mode: :unicode_xss,
         
     | 
| 
      
 30 
     | 
    
         
            +
                float_precision: 0,
         
     | 
| 
      
 31 
     | 
    
         
            +
                hash_class: nil,
         
     | 
| 
      
 32 
     | 
    
         
            +
                ignore: nil,
         
     | 
| 
      
 33 
     | 
    
         
            +
                ignore_under: false,
         
     | 
| 
      
 34 
     | 
    
         
            +
                indent: 0,
         
     | 
| 
      
 35 
     | 
    
         
            +
                integer_range: nil,
         
     | 
| 
      
 36 
     | 
    
         
            +
                mode: :custom,
         
     | 
| 
      
 37 
     | 
    
         
            +
                nan: :raise,
         
     | 
| 
      
 38 
     | 
    
         
            +
                nilnil: false,
         
     | 
| 
      
 39 
     | 
    
         
            +
                object_nl: nil,
         
     | 
| 
      
 40 
     | 
    
         
            +
                omit_nil: false,
         
     | 
| 
      
 41 
     | 
    
         
            +
                quirks_mode: true,
         
     | 
| 
      
 42 
     | 
    
         
            +
                safe: false,
         
     | 
| 
      
 43 
     | 
    
         
            +
                second_precision: 3,
         
     | 
| 
      
 44 
     | 
    
         
            +
                space: nil,
         
     | 
| 
      
 45 
     | 
    
         
            +
                space_before: nil,
         
     | 
| 
      
 46 
     | 
    
         
            +
                symbol_keys: false,
         
     | 
| 
      
 47 
     | 
    
         
            +
                time_format: :ruby,
         
     | 
| 
      
 48 
     | 
    
         
            +
                trace: false,
         
     | 
| 
      
 49 
     | 
    
         
            +
                use_as_json: false,
         
     | 
| 
      
 50 
     | 
    
         
            +
                use_raw_json: false,
         
     | 
| 
      
 51 
     | 
    
         
            +
                use_to_hash: false,
         
     | 
| 
      
 52 
     | 
    
         
            +
                use_to_json: true,
         
     | 
| 
      
 53 
     | 
    
         
            +
              }
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
       11 
55 
     | 
    
         
             
              # A bit hack-ish but does the trick. The JSON.dump_default_options is a Hash
         
     | 
| 
       12 
56 
     | 
    
         
             
              # but in mimic we use a C struct to store defaults. This class creates a view
         
     | 
| 
       13 
57 
     | 
    
         
             
              # onto that struct.
         
     | 
| 
         @@ -38,7 +82,7 @@ module Oj 
     | 
|
| 
       38 
82 
     | 
    
         | 
| 
       39 
83 
     | 
    
         
             
                  jfile = File.join(d, 'json.rb')
         
     | 
| 
       40 
84 
     | 
    
         
             
                  $LOADED_FEATURES << jfile unless $LOADED_FEATURES.include?(jfile) if File.exist?(jfile)
         
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
       42 
86 
     | 
    
         
             
                  Dir.glob(File.join(d, 'json', '**', '*.rb')).each do |file|
         
     | 
| 
       43 
87 
     | 
    
         
             
                    # allow json/add/xxx to be loaded. User can override with Oj.add_to_json(xxx).
         
     | 
| 
       44 
88 
     | 
    
         
             
                    $LOADED_FEATURES << file unless $LOADED_FEATURES.include?(file) unless file.include?('add')
         
     | 
    
        data/lib/oj/version.rb
    CHANGED
    
    
    
        data/lib/oj.rb
    CHANGED
    
    | 
         @@ -2,14 +2,6 @@ 
     | 
|
| 
       2 
2 
     | 
    
         
             
            module Oj
         
     | 
| 
       3 
3 
     | 
    
         
             
            end
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
            begin
         
     | 
| 
       6 
     | 
    
         
            -
              # This require exists to get around Rubinius failing to load bigdecimal from
         
     | 
| 
       7 
     | 
    
         
            -
              # the C extension.
         
     | 
| 
       8 
     | 
    
         
            -
              require 'bigdecimal'
         
     | 
| 
       9 
     | 
    
         
            -
            rescue Exception
         
     | 
| 
       10 
     | 
    
         
            -
              # ignore
         
     | 
| 
       11 
     | 
    
         
            -
            end
         
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
5 
     | 
    
         
             
            require 'oj/version'
         
     | 
| 
       14 
6 
     | 
    
         
             
            require 'oj/bag'
         
     | 
| 
       15 
7 
     | 
    
         
             
            require 'oj/easy_hash'
         
     | 
    
        data/pages/Modes.md
    CHANGED
    
    | 
         @@ -95,7 +95,7 @@ information. 
     | 
|
| 
       95 
95 
     | 
    
         
             
            | :ascii_only            | Boolean |       x |       x |       2 |       2 |       x |       x |         |
         
     | 
| 
       96 
96 
     | 
    
         
             
            | :auto_define           | Boolean |         |         |         |         |       x |       x |         |
         
     | 
| 
       97 
97 
     | 
    
         
             
            | :bigdecimal_as_decimal | Boolean |         |         |         |       3 |       x |       x |         |
         
     | 
| 
       98 
     | 
    
         
            -
            | :bigdecimal_load       | Boolean |         |         | 
     | 
| 
      
 98 
     | 
    
         
            +
            | :bigdecimal_load       | Boolean |         |         |       x |         |         |       x |         |
         
     | 
| 
       99 
99 
     | 
    
         
             
            | :circular              | Boolean |       x |       x |       x |       x |       x |       x |         |
         
     | 
| 
       100 
100 
     | 
    
         
             
            | :class_cache           | Boolean |         |         |         |         |       x |       x |         |
         
     | 
| 
       101 
101 
     | 
    
         
             
            | :create_additions      | Boolean |         |         |       x |       x |         |       x |         |
         
     | 
    
        data/pages/Options.md
    CHANGED
    
    | 
         @@ -66,6 +66,10 @@ Determines how to load decimals. 
     | 
|
| 
       66 
66 
     | 
    
         | 
| 
       67 
67 
     | 
    
         
             
             - `:auto` the most precise for the number of digits is used.
         
     | 
| 
       68 
68 
     | 
    
         | 
| 
      
 69 
     | 
    
         
            +
            This can also be set with `:decimal_class` when used as a load or
         
     | 
| 
      
 70 
     | 
    
         
            +
            parse option to match the JSON gem. In that case either `Float`,
         
     | 
| 
      
 71 
     | 
    
         
            +
            `BigDecimal`, or `nil` can be provided.
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
       69 
73 
     | 
    
         
             
            ### :circular [Boolean]
         
     | 
| 
       70 
74 
     | 
    
         | 
| 
       71 
75 
     | 
    
         
             
            Detect circular references while dumping. In :compat mode raise a
         
     | 
| 
         @@ -80,16 +84,16 @@ dynamically modifying classes or reloading classes then don't use this. 
     | 
|
| 
       80 
84 
     | 
    
         | 
| 
       81 
85 
     | 
    
         
             
            ### :create_additions
         
     | 
| 
       82 
86 
     | 
    
         | 
| 
       83 
     | 
    
         
            -
            A flag indicating the :create_id key when encountered during parsing 
     | 
| 
       84 
     | 
    
         
            -
             
     | 
| 
       85 
     | 
    
         
            -
            with the key.
         
     | 
| 
      
 87 
     | 
    
         
            +
            A flag indicating that the :create_id key, when encountered during parsing,
         
     | 
| 
      
 88 
     | 
    
         
            +
            should create an Object matching the class name specified in the value
         
     | 
| 
      
 89 
     | 
    
         
            +
            associated with the key.
         
     | 
| 
       86 
90 
     | 
    
         | 
| 
       87 
91 
     | 
    
         
             
            ### :create_id [String]
         
     | 
| 
       88 
92 
     | 
    
         | 
| 
       89 
93 
     | 
    
         
             
            The :create_id option specifies that key is used for dumping and loading when
         
     | 
| 
       90 
94 
     | 
    
         
             
            specifying the class for an encoded object. The default is `json_create`.
         
     | 
| 
       91 
95 
     | 
    
         | 
| 
       92 
     | 
    
         
            -
            In the `:custom` mode setting the `:create_id` to nil will cause Complex,
         
     | 
| 
      
 96 
     | 
    
         
            +
            In the `:custom` mode, setting the `:create_id` to nil will cause Complex,
         
     | 
| 
       93 
97 
     | 
    
         
             
            Rational, Range, and Regexp to be output as strings instead of as JSON
         
     | 
| 
       94 
98 
     | 
    
         
             
            objects.
         
     | 
| 
       95 
99 
     | 
    
         | 
| 
         @@ -179,7 +183,7 @@ customization. 
     | 
|
| 
       179 
183 
     | 
    
         
             
            ### :nan [Symbol]
         
     | 
| 
       180 
184 
     | 
    
         | 
| 
       181 
185 
     | 
    
         
             
            How to dump Infinity, -Infinity, and NaN in :null, :strict, and :compat
         
     | 
| 
       182 
     | 
    
         
            -
            mode. Default is :auto but is ignored in the :compat and :rails  
     | 
| 
      
 186 
     | 
    
         
            +
            mode. Default is :auto but is ignored in the :compat and :rails modes.
         
     | 
| 
       183 
187 
     | 
    
         | 
| 
       184 
188 
     | 
    
         
             
             - `:null` places a null
         
     | 
| 
       185 
189 
     | 
    
         | 
| 
         @@ -252,7 +256,7 @@ The :time_format when dumping. 
     | 
|
| 
       252 
256 
     | 
    
         | 
| 
       253 
257 
     | 
    
         
             
             - `:unix` time is output as a decimal number in seconds since epoch including fractions of a second.
         
     | 
| 
       254 
258 
     | 
    
         | 
| 
       255 
     | 
    
         
            -
             - `:unix_zone` similar to the `:unix` format but with the timezone encoded in
         
     | 
| 
      
 259 
     | 
    
         
            +
             - `:unix_zone` is similar to the `:unix` format but with the timezone encoded in
         
     | 
| 
       256 
260 
     | 
    
         
             
               the exponent of the decimal number of seconds since epoch.
         
     | 
| 
       257 
261 
     | 
    
         | 
| 
       258 
262 
     | 
    
         
             
             - `:xmlschema` time is output as a string that follows the XML schema definition.
         
     | 
| 
         @@ -262,16 +266,16 @@ The :time_format when dumping. 
     | 
|
| 
       262 
266 
     | 
    
         
             
            ### :use_as_json [Boolean]
         
     | 
| 
       263 
267 
     | 
    
         | 
| 
       264 
268 
     | 
    
         
             
            Call `as_json()` methods on dump, default is false. The option is ignored in
         
     | 
| 
       265 
     | 
    
         
            -
            the :compat and :rails  
     | 
| 
      
 269 
     | 
    
         
            +
            the :compat and :rails modes.
         
     | 
| 
       266 
270 
     | 
    
         | 
| 
       267 
271 
     | 
    
         | 
| 
       268 
272 
     | 
    
         
             
            ### :use_raw_json [Boolean]
         
     | 
| 
       269 
273 
     | 
    
         | 
| 
       270 
274 
     | 
    
         
             
            Call `raw_json()` methods on dump, default is false. The option is
         
     | 
| 
       271 
     | 
    
         
            -
            accepted in the :compat and :rails  
     | 
| 
      
 275 
     | 
    
         
            +
            accepted in the :compat and :rails modes even though it is not
         
     | 
| 
       272 
276 
     | 
    
         
             
            supported by other JSON gems. It provides a means to optimize dump or
         
     | 
| 
       273 
277 
     | 
    
         
             
            generate performance. The `raw_json(depth, indent)` method should be
         
     | 
| 
       274 
     | 
    
         
            -
            called only by Oj. It is not intended for any other use. This is  
     | 
| 
      
 278 
     | 
    
         
            +
            called only by Oj. It is not intended for any other use. This is meant
         
     | 
| 
       275 
279 
     | 
    
         
             
            to replace the abused `to_json` methods. Calling `Oj.dump` inside the
         
     | 
| 
       276 
280 
     | 
    
         
             
            `raw_json` with the object itself when `:use_raw_json` is true will
         
     | 
| 
       277 
281 
     | 
    
         
             
            result in an infinite loop.
         
     | 
| 
         @@ -279,9 +283,9 @@ result in an infinite loop. 
     | 
|
| 
       279 
283 
     | 
    
         
             
            ### :use_to_hash [Boolean]
         
     | 
| 
       280 
284 
     | 
    
         | 
| 
       281 
285 
     | 
    
         
             
            Call `to_hash()` methods on dump, default is false. The option is ignored in
         
     | 
| 
       282 
     | 
    
         
            -
            the :compat and :rails  
     | 
| 
      
 286 
     | 
    
         
            +
            the :compat and :rails modes.
         
     | 
| 
       283 
287 
     | 
    
         | 
| 
       284 
288 
     | 
    
         
             
            ### :use_to_json [Boolean]
         
     | 
| 
       285 
289 
     | 
    
         | 
| 
       286 
290 
     | 
    
         
             
            Call `to_json()` methods on dump, default is false. The option is ignored in
         
     | 
| 
       287 
     | 
    
         
            -
            the :compat and :rails  
     | 
| 
      
 291 
     | 
    
         
            +
            the :compat and :rails modes.
         
     | 
    
        data/pages/Rails.md
    CHANGED
    
    | 
         @@ -26,44 +26,44 @@ directly. If Rails mode is also desired then use the `Oj.default_options` to 
     | 
|
| 
       26 
26 
     | 
    
         
             
            change the default mode.
         
     | 
| 
       27 
27 
     | 
    
         | 
| 
       28 
28 
     | 
    
         
             
            Some of the Oj options are supported as arguments to the encoder if called
         
     | 
| 
       29 
     | 
    
         
            -
            from Oj::Rails.encode() but when using the Oj::Rails::Encoder class the
         
     | 
| 
       30 
     | 
    
         
            -
            encode() method does not support optional arguments as required by the
         
     | 
| 
      
 29 
     | 
    
         
            +
            from `Oj::Rails.encode()` but when using the `Oj::Rails::Encoder` class the
         
     | 
| 
      
 30 
     | 
    
         
            +
            `encode()` method does not support optional arguments as required by the
         
     | 
| 
       31 
31 
     | 
    
         
             
            ActiveSupport compliance guidelines. The general approach Rails takes for
         
     | 
| 
       32 
32 
     | 
    
         
             
            configuring encoding options is to either set global values or to create a new
         
     | 
| 
       33 
33 
     | 
    
         
             
            instance of the Encoder class and provide options in the initializer.
         
     | 
| 
       34 
34 
     | 
    
         | 
| 
       35 
35 
     | 
    
         
             
            The globals that ActiveSupport uses for encoding are:
         
     | 
| 
       36 
36 
     | 
    
         | 
| 
       37 
     | 
    
         
            -
             * ActiveSupport::JSON::Encoding.use_standard_json_time_format
         
     | 
| 
       38 
     | 
    
         
            -
             * ActiveSupport::JSON::Encoding.escape_html_entities_in_json
         
     | 
| 
       39 
     | 
    
         
            -
             * ActiveSupport::JSON::Encoding.time_precision
         
     | 
| 
       40 
     | 
    
         
            -
             * ActiveSupport::JSON::Encoding.json_encoder
         
     | 
| 
      
 37 
     | 
    
         
            +
             * `ActiveSupport::JSON::Encoding.use_standard_json_time_format`
         
     | 
| 
      
 38 
     | 
    
         
            +
             * `ActiveSupport::JSON::Encoding.escape_html_entities_in_json`
         
     | 
| 
      
 39 
     | 
    
         
            +
             * `ActiveSupport::JSON::Encoding.time_precision`
         
     | 
| 
      
 40 
     | 
    
         
            +
             * `ActiveSupport::JSON::Encoding.json_encoder`
         
     | 
| 
       41 
41 
     | 
    
         | 
| 
       42 
42 
     | 
    
         
             
            Those globals are aliased to also be accessed from the ActiveSupport module
         
     | 
| 
       43 
     | 
    
         
            -
            directly so ActiveSupport::JSON::Encoding.time_precision can also be accessed
         
     | 
| 
       44 
     | 
    
         
            -
            from ActiveSupport.time_precision 
     | 
| 
       45 
     | 
    
         
            -
            Rails after the Oj::Rails.set_encode() method is called. That also sets the
         
     | 
| 
       46 
     | 
    
         
            -
            ActiveSupport.json_encoder to the Oj::Rails::Encoder class.
         
     | 
| 
      
 43 
     | 
    
         
            +
            directly so `ActiveSupport::JSON::Encoding.time_precision` can also be accessed
         
     | 
| 
      
 44 
     | 
    
         
            +
            from `ActiveSupport.time_precision`. Oj makes use of these globals in mimicing
         
     | 
| 
      
 45 
     | 
    
         
            +
            Rails after the `Oj::Rails.set_encode()` method is called. That also sets the
         
     | 
| 
      
 46 
     | 
    
         
            +
            `ActiveSupport.json_encoder` to the `Oj::Rails::Encoder` class.
         
     | 
| 
       47 
47 
     | 
    
         | 
| 
       48 
     | 
    
         
            -
            Options passed into a call to to_json() are passed to the as_json()
         
     | 
| 
      
 48 
     | 
    
         
            +
            Options passed into a call to `to_json()` are passed to the `as_json()`
         
     | 
| 
       49 
49 
     | 
    
         
             
            methods. These are mostly ignored by Oj and simply passed on without
         
     | 
| 
       50 
50 
     | 
    
         
             
            modifications as per the guidelines. The exception to this are the options
         
     | 
| 
       51 
     | 
    
         
            -
            specific to Oj such as the  
     | 
| 
      
 51 
     | 
    
         
            +
            specific to Oj such as the `:circular` option which it used to detect circular
         
     | 
| 
       52 
52 
     | 
    
         
             
            references while encoding.
         
     | 
| 
       53 
53 
     | 
    
         | 
| 
       54 
54 
     | 
    
         
             
            By default Oj acts like the ActiveSupport encoder and honors any changes in
         
     | 
| 
       55 
     | 
    
         
            -
            the as_json() methods. There are some optimized Oj encoders for some
         
     | 
| 
       56 
     | 
    
         
            -
            classes. When the optimized encoder it toggled the as_json() methods will not
         
     | 
| 
      
 55 
     | 
    
         
            +
            the `as_json()` methods. There are some optimized Oj encoders for some
         
     | 
| 
      
 56 
     | 
    
         
            +
            classes. When the optimized encoder it toggled the `as_json()` methods will not
         
     | 
| 
       57 
57 
     | 
    
         
             
            be called for that class but instead the optimized version will be called. The
         
     | 
| 
       58 
58 
     | 
    
         
             
            optimized version is the same as the ActiveSupport default encoding for a
         
     | 
| 
       59 
     | 
    
         
            -
            given class. The optimized versions are toggled with the optimize() and
         
     | 
| 
       60 
     | 
    
         
            -
            deoptimize() methods. There is a default optimized version for every class
         
     | 
| 
      
 59 
     | 
    
         
            +
            given class. The optimized versions are toggled with the `optimize()` and
         
     | 
| 
      
 60 
     | 
    
         
            +
            `deoptimize()` methods. There is a default optimized version for every class
         
     | 
| 
       61 
61 
     | 
    
         
             
            that takes the visible attributes and encodes them but that may not be the
         
     | 
| 
       62 
62 
     | 
    
         
             
            same as what Rails uses. Trial and error is the best approach for classes not
         
     | 
| 
       63 
63 
     | 
    
         
             
            listed here.
         
     | 
| 
       64 
64 
     | 
    
         | 
| 
       65 
65 
     | 
    
         
             
            The classes that can be put in optimized mode and are optimized when
         
     | 
| 
       66 
     | 
    
         
            -
            Oj::Rails.optimize is called with no arguments are:
         
     | 
| 
      
 66 
     | 
    
         
            +
            `Oj::Rails.optimize` is called with no arguments are:
         
     | 
| 
       67 
67 
     | 
    
         | 
| 
       68 
68 
     | 
    
         
             
             * Array
         
     | 
| 
       69 
69 
     | 
    
         
             
             * BigDecimal
         
     | 
| 
         @@ -77,8 +77,47 @@ Oj::Rails.optimize is called with no arguments are: 
     | 
|
| 
       77 
77 
     | 
    
         
             
             * any class inheriting from ActiveRecord::Base
         
     | 
| 
       78 
78 
     | 
    
         
             
             * any other class where all attributes should be dumped
         
     | 
| 
       79 
79 
     | 
    
         | 
| 
       80 
     | 
    
         
            -
            The ActiveSupport decoder is the JSON.parse() method. Calling the
         
     | 
| 
       81 
     | 
    
         
            -
            Oj::Rails.set_decoder() method replaces that method with the Oj equivalent.
         
     | 
| 
      
 80 
     | 
    
         
            +
            The ActiveSupport decoder is the `JSON.parse()` method. Calling the
         
     | 
| 
      
 81 
     | 
    
         
            +
            `Oj::Rails.set_decoder()` method replaces that method with the Oj equivalent.
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
            ### Usage in Rails 3
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
            To support Rails 3 you can create a new module mixin to prepend to controllers:
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 88 
     | 
    
         
            +
            require 'oj'
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
            module OjJsonEncoder
         
     | 
| 
      
 91 
     | 
    
         
            +
              def render(options = nil, extra_options = {}, &block)
         
     | 
| 
      
 92 
     | 
    
         
            +
                if options && options.is_a?(Hash) && options[:json]
         
     | 
| 
      
 93 
     | 
    
         
            +
                  obj = options.delete(:json)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  obj = Oj.dump(obj, :mode => :rails) unless obj.is_a?(String)
         
     | 
| 
      
 95 
     | 
    
         
            +
                  options[:text] = obj
         
     | 
| 
      
 96 
     | 
    
         
            +
                  response.content_type ||= Mime::JSON
         
     | 
| 
      
 97 
     | 
    
         
            +
                end
         
     | 
| 
      
 98 
     | 
    
         
            +
                super
         
     | 
| 
      
 99 
     | 
    
         
            +
              end
         
     | 
| 
      
 100 
     | 
    
         
            +
            end
         
     | 
| 
      
 101 
     | 
    
         
            +
            ```
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
            Usage:
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 106 
     | 
    
         
            +
            class MyController < ApplicationController
         
     | 
| 
      
 107 
     | 
    
         
            +
              prepend OjJsonEncoder
         
     | 
| 
      
 108 
     | 
    
         
            +
              def index
         
     | 
| 
      
 109 
     | 
    
         
            +
                render :json => { :hello => 'world' }
         
     | 
| 
      
 110 
     | 
    
         
            +
              end
         
     | 
| 
      
 111 
     | 
    
         
            +
            end
         
     | 
| 
      
 112 
     | 
    
         
            +
            ```
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
            ### Older Ruby Version Support (Pre 2.3.0)
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
            If you are using an older version of Ruby, you can pin `oj` to an earlier version in your Gemfile:
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 119 
     | 
    
         
            +
            gem 'oj', '3.7.12'
         
     | 
| 
      
 120 
     | 
    
         
            +
            ```
         
     | 
| 
       82 
121 
     | 
    
         | 
| 
       83 
122 
     | 
    
         
             
            ### Notes:
         
     | 
| 
       84 
123 
     | 
    
         | 
| 
         @@ -87,8 +126,8 @@ Oj::Rails.set_decoder() method replaces that method with the Oj equivalent. 
     | 
|
| 
       87 
126 
     | 
    
         
             
               significant digits which can be either 16 or 17 depending on the value.
         
     | 
| 
       88 
127 
     | 
    
         | 
| 
       89 
128 
     | 
    
         
             
            2. Optimized Hashs do not collapse keys that become the same in the output. As
         
     | 
| 
       90 
     | 
    
         
            -
               an example, a non-String object that has a to_s() method will become the
         
     | 
| 
       91 
     | 
    
         
            -
               return value of the to_s() method in the output without checking to see if
         
     | 
| 
      
 129 
     | 
    
         
            +
               an example, a non-String object that has a `to_s()` method will become the
         
     | 
| 
      
 130 
     | 
    
         
            +
               return value of the `to_s()` method in the output without checking to see if
         
     | 
| 
       92 
131 
     | 
    
         
             
               that has already been used. This could occur is a mix of String and Symbols
         
     | 
| 
       93 
132 
     | 
    
         
             
               are used as keys or if a other non-String objects such as Numerics are mixed
         
     | 
| 
       94 
133 
     | 
    
         
             
               with numbers as Strings.
         
     | 
| 
         @@ -0,0 +1,45 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            ORIG_ARGV = ARGV.dup
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            require "active_support/core_ext/kernel/reporting"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            silence_warnings do
         
     | 
| 
      
 8 
     | 
    
         
            +
              Encoding.default_internal = Encoding::UTF_8
         
     | 
| 
      
 9 
     | 
    
         
            +
              Encoding.default_external = Encoding::UTF_8
         
     | 
| 
      
 10 
     | 
    
         
            +
            end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            require "active_support/testing/autorun"
         
     | 
| 
      
 13 
     | 
    
         
            +
            require "active_support/testing/method_call_assertions"
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            ENV["NO_RELOAD"] = "1"
         
     | 
| 
      
 16 
     | 
    
         
            +
            require "active_support"
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            Thread.abort_on_exception = true
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            # Show backtraces for deprecated behavior for quicker cleanup.
         
     | 
| 
      
 21 
     | 
    
         
            +
            ActiveSupport::Deprecation.debug = true
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            # Default to old to_time behavior but allow running tests with new behavior
         
     | 
| 
      
 24 
     | 
    
         
            +
            ActiveSupport.to_time_preserves_timezone = ENV["PRESERVE_TIMEZONES"] == "1"
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            # Disable available locale checks to avoid warnings running the test suite.
         
     | 
| 
      
 27 
     | 
    
         
            +
            I18n.enforce_available_locales = false
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            class ActiveSupport::TestCase
         
     | 
| 
      
 30 
     | 
    
         
            +
              include ActiveSupport::Testing::MethodCallAssertions
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              # Skips the current run on Rubinius using Minitest::Assertions#skip
         
     | 
| 
      
 33 
     | 
    
         
            +
              private def rubinius_skip(message = "")
         
     | 
| 
      
 34 
     | 
    
         
            +
                skip message if RUBY_ENGINE == "rbx"
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
              # Skips the current run on JRuby using Minitest::Assertions#skip
         
     | 
| 
      
 38 
     | 
    
         
            +
              private def jruby_skip(message = "")
         
     | 
| 
      
 39 
     | 
    
         
            +
                skip message if defined?(JRUBY_VERSION)
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              def frozen_error_class
         
     | 
| 
      
 43 
     | 
    
         
            +
                Object.const_defined?(:FrozenError) ? FrozenError : RuntimeError
         
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,7 +1,9 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
            require  
     | 
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative "abstract_unit"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "active_support/json"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "active_support/time"
         
     | 
| 
      
 6 
     | 
    
         
            +
            require_relative "time_zone_test_helpers"
         
     | 
| 
       5 
7 
     | 
    
         | 
| 
       6 
8 
     | 
    
         
             
            require 'oj'
         
     | 
| 
       7 
9 
     | 
    
         | 
| 
         @@ -10,6 +12,11 @@ Oj::Rails.set_decoder() 
     | 
|
| 
       10 
12 
     | 
    
         
             
            class TestJSONDecoding < ActiveSupport::TestCase
         
     | 
| 
       11 
13 
     | 
    
         
             
              include TimeZoneTestHelpers
         
     | 
| 
       12 
14 
     | 
    
         | 
| 
      
 15 
     | 
    
         
            +
              # Added for testing if Oj is used.
         
     | 
| 
      
 16 
     | 
    
         
            +
              test "oj is used as an encoder" do
         
     | 
| 
      
 17 
     | 
    
         
            +
                assert_equal ActiveSupport.json_encoder, Oj::Rails::Encoder
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
       13 
20 
     | 
    
         
             
              class Foo
         
     | 
| 
       14 
21 
     | 
    
         
             
                def self.json_create(object)
         
     | 
| 
       15 
22 
     | 
    
         
             
                  "Foo"
         
     | 
| 
         @@ -17,76 +24,78 @@ class TestJSONDecoding < ActiveSupport::TestCase 
     | 
|
| 
       17 
24 
     | 
    
         
             
              end
         
     | 
| 
       18 
25 
     | 
    
         | 
| 
       19 
26 
     | 
    
         
             
              TESTS = {
         
     | 
| 
       20 
     | 
    
         
            -
                %q({"returnTo":{"\/categories":"\/"}})        => {"returnTo" => {"/categories" => "/"}},
         
     | 
| 
       21 
     | 
    
         
            -
                %q({"return\\"To\\":":{"\/categories":"\/"}}) => {"return\"To\":" => {"/categories" => "/"}},
         
     | 
| 
       22 
     | 
    
         
            -
                %q({"returnTo":{"\/categories":1}}) 
     | 
| 
       23 
     | 
    
         
            -
                %({"returnTo":[1,"a"]})                    => {"returnTo" => [1, "a"]},
         
     | 
| 
       24 
     | 
    
         
            -
                %({"returnTo":[1,"\\"a\\",", "b"]})        => {"returnTo" => [1, "\"a\",", "b"]},
         
     | 
| 
       25 
     | 
    
         
            -
                %({"a": "'", "b": "5,000"})                  => {"a" => "'", "b" => "5,000"},
         
     | 
| 
       26 
     | 
    
         
            -
                %({"a": "a's, b's and c's", "b": "5,000"})   => {"a" => "a's, b's and c's", "b" => "5,000"},
         
     | 
| 
      
 27 
     | 
    
         
            +
                %q({"returnTo":{"\/categories":"\/"}})        => { "returnTo" => { "/categories" => "/" } },
         
     | 
| 
      
 28 
     | 
    
         
            +
                %q({"return\\"To\\":":{"\/categories":"\/"}}) => { "return\"To\":" => { "/categories" => "/" } },
         
     | 
| 
      
 29 
     | 
    
         
            +
                %q({"returnTo":{"\/categories":1}}) => { "returnTo" => { "/categories" => 1 } },
         
     | 
| 
      
 30 
     | 
    
         
            +
                %({"returnTo":[1,"a"]})                    => { "returnTo" => [1, "a"] },
         
     | 
| 
      
 31 
     | 
    
         
            +
                %({"returnTo":[1,"\\"a\\",", "b"]})        => { "returnTo" => [1, "\"a\",", "b"] },
         
     | 
| 
      
 32 
     | 
    
         
            +
                %({"a": "'", "b": "5,000"})                  => { "a" => "'", "b" => "5,000" },
         
     | 
| 
      
 33 
     | 
    
         
            +
                %({"a": "a's, b's and c's", "b": "5,000"})   => { "a" => "a's, b's and c's", "b" => "5,000" },
         
     | 
| 
       27 
34 
     | 
    
         
             
                # multibyte
         
     | 
| 
       28 
     | 
    
         
            -
                %({"matzue": "松江", "asakusa": "浅草"}) => {"matzue" => "松江", "asakusa" => "浅草"},
         
     | 
| 
       29 
     | 
    
         
            -
                %({"a": "2007-01-01"})                       => { 
     | 
| 
       30 
     | 
    
         
            -
                %({"a": "2007-01-01 01:12:34 Z"})            => { 
     | 
| 
      
 35 
     | 
    
         
            +
                %({"matzue": "松江", "asakusa": "浅草"}) => { "matzue" => "松江", "asakusa" => "浅草" },
         
     | 
| 
      
 36 
     | 
    
         
            +
                %({"a": "2007-01-01"})                       => { "a" => Date.new(2007, 1, 1) },
         
     | 
| 
      
 37 
     | 
    
         
            +
                %({"a": "2007-01-01 01:12:34 Z"})            => { "a" => Time.utc(2007, 1, 1, 1, 12, 34) },
         
     | 
| 
       31 
38 
     | 
    
         
             
                %(["2007-01-01 01:12:34 Z"])                 => [Time.utc(2007, 1, 1, 1, 12, 34)],
         
     | 
| 
       32 
39 
     | 
    
         
             
                %(["2007-01-01 01:12:34 Z", "2007-01-01 01:12:35 Z"]) => [Time.utc(2007, 1, 1, 1, 12, 34), Time.utc(2007, 1, 1, 1, 12, 35)],
         
     | 
| 
       33 
40 
     | 
    
         
             
                # no time zone
         
     | 
| 
       34 
     | 
    
         
            -
                %({"a": "2007-01-01 01:12:34"})              => { 
     | 
| 
      
 41 
     | 
    
         
            +
                %({"a": "2007-01-01 01:12:34"})              => { "a" => Time.new(2007, 1, 1, 1, 12, 34, "-05:00") },
         
     | 
| 
       35 
42 
     | 
    
         
             
                # invalid date
         
     | 
| 
       36 
     | 
    
         
            -
                %({"a": "1089-10-40"})                       => { 
     | 
| 
      
 43 
     | 
    
         
            +
                %({"a": "1089-10-40"})                       => { "a" => "1089-10-40" },
         
     | 
| 
       37 
44 
     | 
    
         
             
                # xmlschema date notation
         
     | 
| 
       38 
     | 
    
         
            -
                %({"a": "2009-08-10T19:01:02"})              => { 
     | 
| 
       39 
     | 
    
         
            -
                %({"a": "2009-08-10T19:01:02Z"})             => { 
     | 
| 
       40 
     | 
    
         
            -
                %({"a": "2009-08-10T19:01:02+02:00"})        => { 
     | 
| 
       41 
     | 
    
         
            -
                %({"a": "2009-08-10T19:01:02-05:00"})        => { 
     | 
| 
      
 45 
     | 
    
         
            +
                %({"a": "2009-08-10T19:01:02"})              => { "a" => Time.new(2009, 8, 10, 19, 1, 2, "-04:00") },
         
     | 
| 
      
 46 
     | 
    
         
            +
                %({"a": "2009-08-10T19:01:02Z"})             => { "a" => Time.utc(2009, 8, 10, 19, 1, 2) },
         
     | 
| 
      
 47 
     | 
    
         
            +
                %({"a": "2009-08-10T19:01:02+02:00"})        => { "a" => Time.utc(2009, 8, 10, 17, 1, 2) },
         
     | 
| 
      
 48 
     | 
    
         
            +
                %({"a": "2009-08-10T19:01:02-05:00"})        => { "a" => Time.utc(2009, 8, 11, 00, 1, 2) },
         
     | 
| 
       42 
49 
     | 
    
         
             
                # needs to be *exact*
         
     | 
| 
       43 
     | 
    
         
            -
                %({"a": " 2007-01-01 01:12:34 Z "})          => { 
     | 
| 
       44 
     | 
    
         
            -
                %({"a": "2007-01-01 : it's your birthday"})  => { 
     | 
| 
      
 50 
     | 
    
         
            +
                %({"a": " 2007-01-01 01:12:34 Z "})          => { "a" => " 2007-01-01 01:12:34 Z " },
         
     | 
| 
      
 51 
     | 
    
         
            +
                %({"a": "2007-01-01 : it's your birthday"})  => { "a" => "2007-01-01 : it's your birthday" },
         
     | 
| 
       45 
52 
     | 
    
         
             
                %([])    => [],
         
     | 
| 
       46 
53 
     | 
    
         
             
                %({})    => {},
         
     | 
| 
       47 
     | 
    
         
            -
                %({"a":1}) 
     | 
| 
       48 
     | 
    
         
            -
                %({"a": ""}) 
     | 
| 
       49 
     | 
    
         
            -
                %({"a":"\\""}) => {"a" => "\""},
         
     | 
| 
       50 
     | 
    
         
            -
                %({"a": null})  => {"a" => nil},
         
     | 
| 
       51 
     | 
    
         
            -
                %({"a": true})  => {"a" => true},
         
     | 
| 
       52 
     | 
    
         
            -
                %({"a": false}) => {"a" => false},
         
     | 
| 
       53 
     | 
    
         
            -
                 
     | 
| 
       54 
     | 
    
         
            -
                %q({"a": "http:\/\/test.host\/posts\/1"}) => {"a" => "http://test.host/posts/1"},
         
     | 
| 
       55 
     | 
    
         
            -
                %q({"a": "\u003cunicode\u0020escape\u003e"}) => {"a" => "<unicode escape>"},
         
     | 
| 
       56 
     | 
    
         
            -
                 
     | 
| 
       57 
     | 
    
         
            -
                %q({"a": "\u003cbr /\u003e"}) => { 
     | 
| 
       58 
     | 
    
         
            -
                %q({"b":["\u003ci\u003e","\u003cb\u003e","\u003cu\u003e"]}) => { 
     | 
| 
      
 54 
     | 
    
         
            +
                %({"a":1}) => { "a" => 1 },
         
     | 
| 
      
 55 
     | 
    
         
            +
                %({"a": ""}) => { "a" => "" },
         
     | 
| 
      
 56 
     | 
    
         
            +
                %({"a":"\\""}) => { "a" => "\"" },
         
     | 
| 
      
 57 
     | 
    
         
            +
                %({"a": null})  => { "a" => nil },
         
     | 
| 
      
 58 
     | 
    
         
            +
                %({"a": true})  => { "a" => true },
         
     | 
| 
      
 59 
     | 
    
         
            +
                %({"a": false}) => { "a" => false },
         
     | 
| 
      
 60 
     | 
    
         
            +
                '{"bad":"\\\\","trailing":""}' => { "bad" => "\\", "trailing" => "" },
         
     | 
| 
      
 61 
     | 
    
         
            +
                %q({"a": "http:\/\/test.host\/posts\/1"}) => { "a" => "http://test.host/posts/1" },
         
     | 
| 
      
 62 
     | 
    
         
            +
                %q({"a": "\u003cunicode\u0020escape\u003e"}) => { "a" => "<unicode escape>" },
         
     | 
| 
      
 63 
     | 
    
         
            +
                '{"a": "\\\\u0020skip double backslashes"}' => { "a" => "\\u0020skip double backslashes" },
         
     | 
| 
      
 64 
     | 
    
         
            +
                %q({"a": "\u003cbr /\u003e"}) => { "a" => "<br />" },
         
     | 
| 
      
 65 
     | 
    
         
            +
                %q({"b":["\u003ci\u003e","\u003cb\u003e","\u003cu\u003e"]}) => { "b" => ["<i>", "<b>", "<u>"] },
         
     | 
| 
       59 
66 
     | 
    
         
             
                # test combination of dates and escaped or unicode encoded data in arrays
         
     | 
| 
       60 
67 
     | 
    
         
             
                %q([{"d":"1970-01-01", "s":"\u0020escape"},{"d":"1970-01-01", "s":"\u0020escape"}]) =>
         
     | 
| 
       61 
     | 
    
         
            -
                  [{ 
     | 
| 
      
 68 
     | 
    
         
            +
                  [{ "d" => Date.new(1970, 1, 1), "s" => " escape" }, { "d" => Date.new(1970, 1, 1), "s" => " escape" }],
         
     | 
| 
       62 
69 
     | 
    
         
             
                %q([{"d":"1970-01-01","s":"http:\/\/example.com"},{"d":"1970-01-01","s":"http:\/\/example.com"}]) =>
         
     | 
| 
       63 
     | 
    
         
            -
                  [{ 
     | 
| 
       64 
     | 
    
         
            -
                   { 
     | 
| 
      
 70 
     | 
    
         
            +
                  [{ "d" => Date.new(1970, 1, 1), "s" => "http://example.com" },
         
     | 
| 
      
 71 
     | 
    
         
            +
                   { "d" => Date.new(1970, 1, 1), "s" => "http://example.com" }],
         
     | 
| 
       65 
72 
     | 
    
         
             
                # tests escaping of "\n" char with Yaml backend
         
     | 
| 
       66 
     | 
    
         
            -
                %q({"a":"\n"}) 
     | 
| 
       67 
     | 
    
         
            -
                %q({"a":"\u000a"}) => {"a"=>"\n"},
         
     | 
| 
       68 
     | 
    
         
            -
                %q({"a":"Line1\u000aLine2"}) => {"a"=>"Line1\nLine2"},
         
     | 
| 
      
 73 
     | 
    
         
            +
                %q({"a":"\n"}) => { "a" => "\n" },
         
     | 
| 
      
 74 
     | 
    
         
            +
                %q({"a":"\u000a"}) => { "a" => "\n" },
         
     | 
| 
      
 75 
     | 
    
         
            +
                %q({"a":"Line1\u000aLine2"}) => { "a" => "Line1\nLine2" },
         
     | 
| 
       69 
76 
     | 
    
         
             
                # prevent json unmarshalling
         
     | 
| 
       70 
     | 
    
         
            -
                 
     | 
| 
      
 77 
     | 
    
         
            +
                '{"json_class":"TestJSONDecoding::Foo"}' => { "json_class" => "TestJSONDecoding::Foo" },
         
     | 
| 
       71 
78 
     | 
    
         
             
                # json "fragments" - these are invalid JSON, but ActionPack relies on this
         
     | 
| 
       72 
     | 
    
         
            -
                 
     | 
| 
       73 
     | 
    
         
            -
                 
     | 
| 
       74 
     | 
    
         
            -
                 
     | 
| 
       75 
     | 
    
         
            -
                 
     | 
| 
       76 
     | 
    
         
            -
                 
     | 
| 
       77 
     | 
    
         
            -
                 
     | 
| 
       78 
     | 
    
         
            -
                 
     | 
| 
      
 79 
     | 
    
         
            +
                '"a string"' => "a string",
         
     | 
| 
      
 80 
     | 
    
         
            +
                "1.1" => 1.1,
         
     | 
| 
      
 81 
     | 
    
         
            +
                "1" => 1,
         
     | 
| 
      
 82 
     | 
    
         
            +
                "-1" => -1,
         
     | 
| 
      
 83 
     | 
    
         
            +
                "true" => true,
         
     | 
| 
      
 84 
     | 
    
         
            +
                "false" => false,
         
     | 
| 
      
 85 
     | 
    
         
            +
                "null" => nil
         
     | 
| 
       79 
86 
     | 
    
         
             
              }
         
     | 
| 
       80 
87 
     | 
    
         | 
| 
       81 
88 
     | 
    
         
             
              TESTS.each_with_index do |(json, expected), index|
         
     | 
| 
      
 89 
     | 
    
         
            +
                fail_message = "JSON decoding failed for #{json}"
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
       82 
91 
     | 
    
         
             
                test "json decodes #{index}" do
         
     | 
| 
       83 
     | 
    
         
            -
                  with_tz_default  
     | 
| 
      
 92 
     | 
    
         
            +
                  with_tz_default "Eastern Time (US & Canada)" do
         
     | 
| 
       84 
93 
     | 
    
         
             
                    with_parse_json_times(true) do
         
     | 
| 
       85 
94 
     | 
    
         
             
                      silence_warnings do
         
     | 
| 
       86 
95 
     | 
    
         
             
                        if expected.nil?
         
     | 
| 
       87 
     | 
    
         
            -
                          assert_nil 
     | 
| 
      
 96 
     | 
    
         
            +
                          assert_nil ActiveSupport::JSON.decode(json), fail_message
         
     | 
| 
       88 
97 
     | 
    
         
             
                        else
         
     | 
| 
       89 
     | 
    
         
            -
                          assert_equal 
     | 
| 
      
 98 
     | 
    
         
            +
                          assert_equal expected, ActiveSupport::JSON.decode(json), fail_message
         
     | 
| 
       90 
99 
     | 
    
         
             
                        end
         
     | 
| 
       91 
100 
     | 
    
         
             
                      end
         
     | 
| 
       92 
101 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -96,7 +105,7 @@ class TestJSONDecoding < ActiveSupport::TestCase 
     | 
|
| 
       96 
105 
     | 
    
         | 
| 
       97 
106 
     | 
    
         
             
              test "json decodes time json with time parsing disabled" do
         
     | 
| 
       98 
107 
     | 
    
         
             
                with_parse_json_times(false) do
         
     | 
| 
       99 
     | 
    
         
            -
                  expected = {"a" => "2007-01-01 01:12:34 Z"}
         
     | 
| 
      
 108 
     | 
    
         
            +
                  expected = { "a" => "2007-01-01 01:12:34 Z" }
         
     | 
| 
       100 
109 
     | 
    
         
             
                  assert_equal expected, ActiveSupport::JSON.decode(%({"a": "2007-01-01 01:12:34 Z"}))
         
     | 
| 
       101 
110 
     | 
    
         
             
                end
         
     | 
| 
       102 
111 
     | 
    
         
             
              end
         
     | 
| 
         @@ -114,12 +123,11 @@ class TestJSONDecoding < ActiveSupport::TestCase 
     | 
|
| 
       114 
123 
     | 
    
         | 
| 
       115 
124 
     | 
    
         
             
              private
         
     | 
| 
       116 
125 
     | 
    
         | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
       119 
     | 
    
         
            -
             
     | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
       122 
     | 
    
         
            -
             
     | 
| 
       123 
     | 
    
         
            -
             
     | 
| 
      
 126 
     | 
    
         
            +
                def with_parse_json_times(value)
         
     | 
| 
      
 127 
     | 
    
         
            +
                  old_value = ActiveSupport.parse_json_times
         
     | 
| 
      
 128 
     | 
    
         
            +
                  ActiveSupport.parse_json_times = value
         
     | 
| 
      
 129 
     | 
    
         
            +
                  yield
         
     | 
| 
      
 130 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 131 
     | 
    
         
            +
                  ActiveSupport.parse_json_times = old_value
         
     | 
| 
      
 132 
     | 
    
         
            +
                end
         
     | 
| 
       124 
133 
     | 
    
         
             
            end
         
     | 
| 
       125 
     | 
    
         
            -
             
     |