Class: Oj::Rails::Encoder

Inherits:
Object
  • Object
show all
Defined in:
ext/oj/rails.c,
ext/oj/rails.c

Overview

The Oj ActiveSupport compliant encoder.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.new(*args) ⇒ Object



754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
# File 'ext/oj/rails.c', line 754

static VALUE encoder_new(int argc, VALUE *argv, VALUE self) {
    Encoder e = OJ_R_ALLOC(struct _encoder);

    e->ropts.len   = 0;
    e->ropts.alen  = 0;
    e->ropts.table = NULL;
    e->own_ropts   = false;

    if (1 <= argc && Qnil != *argv) {
        e->arg = *argv;
    } else {
        e->arg = rb_hash_new();
    }
    // An encoder given no options of its own reads oj_default_options at encode
    // time rather than copying it here. ActiveSupport keeps one option-less
    // encoder for the life of the process, so a copy taken now would freeze
    // every later Oj.default_options and ActiveSupport::JSON::Encoding change
    // out of it - including the time_precision that set_encoder itself writes
    // after ActiveSupport has already built and cached that encoder.
    e->own_opts = T_HASH == rb_type(e->arg) && 0 < RHASH_SIZE(e->arg);
    if (e->own_opts) {
        e->opts = oj_default_options;
        // Detach from the match_string regexps owned by the defaults before the
        // options are parsed so that a :match_string option builds a chain of
        // its own that is freed with the encoder.
        e->opts.str_rx.head = NULL;
        e->opts.str_rx.tail = NULL;
        oj_parse_options(e->arg, &e->opts);
        oj_options_take_ownership(&e->opts);
    } else {
        memset(&e->opts, 0, sizeof(e->opts));
    }

    return TypedData_Wrap_Struct(encoder_class, &oj_encoder_type, e);
}

Instance Method Details

#deoptimize(*args) ⇒ Object



935
936
937
938
939
940
941
942
# File 'ext/oj/rails.c', line 935

static VALUE encoder_deoptimize(int argc, VALUE *argv, VALUE self) {
    Encoder e;
    TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);

    optimize(argc, argv, encoder_own_ropts(e), false);

    return Qnil;
}

#encode(obj) ⇒ Object



1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
# File 'ext/oj/rails.c', line 1074

static VALUE encoder_encode(VALUE self, VALUE obj) {
    Encoder e;
    TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);

    if (Qnil != e->arg) {
        // as_json is allowed to write into the options hash it is handed, and
        // the ActiveSupport suite has a test that does exactly that. Handing
        // out the encoder's own hash lets one such call poison every later
        // encode by the same encoder, which on ActiveSupport 8.1 is every
        // option-less to_json in the process because json_encoder= caches one
        // encoder and keeps it. Rails never exposes a hash it will reuse:
        // JSONGemEncoder#encode passes options.dup, and only when there are
        // options at all, so with none as_json writes into its own default.
        // The copy is not frozen the way Rails 8.0 and later freeze theirs,
        // because Oj hands as_json the hash even when it is empty and that is
        // exactly the case Rails leaves writable.
        VALUE argv[1] = {T_HASH == rb_type(e->arg) ? rb_hash_dup(e->arg) : e->arg};

        return encode(obj, encoder_ropts(e), encoder_opts(e), 1, argv);
    }
    return encode(obj, encoder_ropts(e), encoder_opts(e), 0, NULL);
}

#optimize(*args) ⇒ Object



878
879
880
881
882
883
884
885
# File 'ext/oj/rails.c', line 878

static VALUE encoder_optimize(int argc, VALUE *argv, VALUE self) {
    Encoder e;
    TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);

    optimize(argc, argv, encoder_own_ropts(e), true);

    return Qnil;
}

#optimized?(clas) ⇒ Object



965
966
967
968
969
970
971
972
973
974
975
976
# File 'ext/oj/rails.c', line 965

static VALUE encoder_optimized(VALUE self, VALUE clas) {
    Encoder e;
    ROpt    ro;

    TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);
    ro = oj_rails_get_opt(encoder_ropts(e), clas);

    if (NULL == ro) {
        return Qfalse;
    }
    return (ro->on) ? Qtrue : Qfalse;
}