module JSON
A mimic of the json gem module.
Constants
- FAST_STATE_PROTOTYPE
- Infinity
- MinusInfinity
- NaN
- PRETTY_STATE_PROTOTYPE
Taken from the unit test. Note that items like check_circular? are not present.
- Parser
- SAFE_STATE_PROTOTYPE
- State
Public Class Methods
If the obj argument is a String then it is assumed to be a JSON String and parsed otherwise the obj is encoded as a JSON String.
-
obj [String|Hash|Array] object to convert
-
opts [Hash] same options as either generate or parse
Returns [Object]
static VALUE mimic_dump_load(int argc, VALUE *argv, VALUE self) {
if (1 > argc) {
rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
}
if (T_STRING == rb_type(*argv)) {
return mimic_load(argc, argv, self);
}
return mimic_dump(argc, argv, self);
}
Returns [String] the create_id.
static VALUE mimic_create_id(VALUE self) {
if (NULL != oj_default_options.create_id) {
return rb_utf8_str_new(oj_default_options.create_id, oj_default_options.create_id_len);
}
return rb_str_new_cstr(oj_json_class);
}
Sets the create_id tag to look for in JSON document. That key triggers the creation of a class with the same name.
-
id [nil|String] new
create_id
Returns [nil|String] the id.
static VALUE mimic_set_create_id(VALUE self, VALUE id) {
if (NULL != oj_default_options.create_id) {
if (oj_json_class != oj_default_options.create_id) {
OJ_R_FREE((char *)oj_default_options.create_id);
}
oj_default_options.create_id = NULL;
oj_default_options.create_id_len = 0;
}
if (Qnil != id) {
const char *ptr = StringValueCStr(id);
size_t len = RSTRING_LEN(id) + 1;
oj_default_options.create_id = OJ_R_ALLOC_N(char, len);
strcpy((char *)oj_default_options.create_id, ptr);
oj_default_options.create_id_len = len - 1;
}
return id;
}
Encodes an object as a JSON String.
-
obj [Object] object to convert to encode as
JSON -
anIO [IO] an IO that allows writing
-
limit [Fixnum] ignored
Returns [String] a JSON string.
static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
struct _out out;
struct _options copts = oj_default_options;
VALUE rstr;
VALUE active_hack[1];
copts.str_rx.head = NULL;
copts.str_rx.tail = NULL;
oj_out_init(&out);
out.caller = CALLER_DUMP;
copts.escape_mode = JXEsc;
copts.mode = CompatMode;
/* seems like this is not correct
if (No == copts.nilnil && Qnil == *argv) {
rb_raise(rb_eTypeError, "nil not allowed.");
}
*/
copts.dump_opts.max_depth = MAX_DEPTH; // when using dump there is no limit
out.omit_nil = copts.dump_opts.omit_nil;
if (2 <= argc) {
int limit;
// The json gem take a more liberal approach to optional
// arguments. Expected are (obj, anIO=nil, limit=nil) yet the io
// argument can be left off completely and the 2nd argument is then
// the limit.
if (0 <= (limit = mimic_limit_arg(argv[1]))) {
copts.dump_opts.max_depth = limit;
}
if (3 <= argc && 0 <= (limit = mimic_limit_arg(argv[2]))) {
copts.dump_opts.max_depth = limit;
}
}
// ActiveSupport in active_support/core_ext/object/json.rb check the
// optional argument type to to_json and it the argument is a
// ::JSON::State it calls the JSON gem code otherwise it calls the active
// support encoder code. To make sure the desired branch is called a
// default ::JSON::State argument is passed in. Basically a hack to get
// around the active support hack so two wrongs make a right this time.
active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
oj_dump_obj_to_json_using_params(*argv, &copts, &out, 1, active_hack);
if (0 == out.buf) {
rb_raise(rb_eNoMemError, "Not enough memory.");
}
rstr = rb_str_new2(out.buf);
rstr = oj_encode(rstr);
if (2 <= argc && Qnil != argv[1] && rb_respond_to(argv[1], oj_write_id)) {
VALUE io = argv[1];
VALUE args[1];
*args = rstr;
rb_funcall2(io, oj_write_id, 1, args);
rstr = io;
}
oj_out_free(&out);
return rstr;
}
# File lib/oj/json.rb, line 47 def self.dump_default_options Oj::MimicDumpOption.new end
# File lib/oj/json.rb, line 51 def self.dump_default_options=(h) m = Oj::MimicDumpOption.new h.each do |k, v| m[k] = v end end
VALUE
oj_mimic_generate(int argc, VALUE *argv, VALUE self) {
struct _options copts = oj_default_options;
copts.str_rx.head = NULL;
copts.str_rx.tail = NULL;
return mimic_generate_core(argc, argv, &copts);
}
Encode obj as a JSON String. The obj argument must be a Hash, Array, or respond to to_h or to_json. Options other than those listed such as :allow_nan or :max_nesting are ignored.
-
opts [Hash] options
Note JSON.generate does support this even if it is not documented.
Returns [String] generated JSON.
VALUE
oj_mimic_generate(int argc, VALUE *argv, VALUE self) {
struct _options copts = oj_default_options;
copts.str_rx.head = NULL;
copts.str_rx.tail = NULL;
return mimic_generate_core(argc, argv, &copts);
}
Encode obj as a JSON String. The obj argument must be a Hash, Array, or respond to to_h or to_json. Options other than those listed such as :allow_nan or :max_nesting are ignored.
-
opts [Hash] options
Note JSON.generate does support this even if it is not documented.
Returns [String] generated JSON.
VALUE
oj_mimic_generate(int argc, VALUE *argv, VALUE self) {
struct _options copts = oj_default_options;
copts.str_rx.head = NULL;
copts.str_rx.tail = NULL;
return mimic_generate_core(argc, argv, &copts);
}
# File lib/oj/json.rb, line 70 def self.generator() @@generator end
# File lib/oj/json.rb, line 66 def self.generator=(g) @@generator = g end
Loads a Ruby Object from a JSON source that can be either a String or an IO. If Proc is given or a block is provided it is called with each nested element of the loaded Object.
-
source [String|IO]
JSONsource -
proc [Proc] to yield to on each element or nil
Returns [Object] the decode Object.
static VALUE mimic_load(int argc, VALUE *argv, VALUE self) {
VALUE obj;
VALUE p = Qnil;
obj = oj_compat_load(argc, argv, self);
if (2 <= argc) {
if (rb_cProc == rb_obj_class(argv[1])) {
p = argv[1];
} else if (3 <= argc) {
if (rb_cProc == rb_obj_class(argv[2])) {
p = argv[2];
}
}
}
mimic_walk(Qnil, obj, p);
return obj;
}
Parses a JSON String or IO into a Ruby Object. Options other than those listed such as :allow_nan or :max_nesting are ignored. :object_class and :array_object are not supported.
-
source [String|IO] source to parse
-
opts [Hash] options
-
:symbolize [Boolean] _names flag indicating
JSONobject keys should be Symbols instead of
-
Strings
- *:create_additions* [Boolean] flag indicating a key matching +create_id+ in a JSON object
should trigger the creation of Ruby Object
Returns [Object] @see create_id=
VALUE
oj_mimic_parse(int argc, VALUE *argv, VALUE self) {
return mimic_parse_core(argc, argv, self, false);
}
Same as parse(). @see parse
static VALUE mimic_parse_bang(int argc, VALUE *argv, VALUE self) {
return mimic_parse_core(argc, argv, self, true);
}
# File lib/oj/json.rb, line 62 def self.parser() @@parser end
# File lib/oj/json.rb, line 58 def self.parser=(p) @@parser = p end
Same as generate() but with different defaults for the spacing options. @see generate
Return [String] the generated JSON.
VALUE
oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
struct _options copts = oj_default_options;
VALUE rargs[2];
volatile VALUE h;
// Some (all?) json gem to_json methods need a State instance and not just
// a Hash. I haven't dug deep enough to find out why but using a State
// instance and not a Hash gives the desired behavior.
*rargs = *argv;
if (0 == argc) {
rb_raise(rb_eArgError, "wrong number of arguments (0))");
}
if (1 == argc || Qnil == argv[1]) {
h = rb_hash_new();
} else {
h = argv[1];
}
if (!oj_hash_has_key(h, oj_indent_sym)) {
rb_hash_aset(h, oj_indent_sym, rb_str_new2(" "));
}
if (!oj_hash_has_key(h, oj_space_before_sym)) {
rb_hash_aset(h, oj_space_before_sym, rb_str_new2(""));
}
if (!oj_hash_has_key(h, oj_space_sym)) {
rb_hash_aset(h, oj_space_sym, rb_str_new2(" "));
}
if (!oj_hash_has_key(h, oj_object_nl_sym)) {
rb_hash_aset(h, oj_object_nl_sym, rb_str_new2("\n"));
}
if (!oj_hash_has_key(h, oj_array_nl_sym)) {
rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
}
if (Qundef == state_class) {
rb_warn("Oj::Rails.mimic_JSON was called implicitly. "
"Call it explicitly beforehand if you want to remove this warning.");
oj_define_mimic_json(0, NULL, Qnil);
}
rargs[1] = rb_funcall(state_class, oj_new_id, 1, h);
copts.str_rx.head = NULL;
copts.str_rx.tail = NULL;
strcpy(copts.dump_opts.indent_str, " ");
copts.dump_opts.indent_size = (uint8_t)strlen(copts.dump_opts.indent_str);
strcpy(copts.dump_opts.before_sep, "");
copts.dump_opts.before_size = (uint8_t)strlen(copts.dump_opts.before_sep);
strcpy(copts.dump_opts.after_sep, " ");
copts.dump_opts.after_size = (uint8_t)strlen(copts.dump_opts.after_sep);
strcpy(copts.dump_opts.hash_nl, "\n");
copts.dump_opts.hash_size = (uint8_t)strlen(copts.dump_opts.hash_nl);
strcpy(copts.dump_opts.array_nl, "\n");
copts.dump_opts.array_size = (uint8_t)strlen(copts.dump_opts.array_nl);
copts.dump_opts.use = true;
return mimic_generate_core(2, rargs, &copts);
}
Same as generate() but with different defaults for the spacing options. @see generate
Return [String] the generated JSON.
VALUE
oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
struct _options copts = oj_default_options;
VALUE rargs[2];
volatile VALUE h;
// Some (all?) json gem to_json methods need a State instance and not just
// a Hash. I haven't dug deep enough to find out why but using a State
// instance and not a Hash gives the desired behavior.
*rargs = *argv;
if (0 == argc) {
rb_raise(rb_eArgError, "wrong number of arguments (0))");
}
if (1 == argc || Qnil == argv[1]) {
h = rb_hash_new();
} else {
h = argv[1];
}
if (!oj_hash_has_key(h, oj_indent_sym)) {
rb_hash_aset(h, oj_indent_sym, rb_str_new2(" "));
}
if (!oj_hash_has_key(h, oj_space_before_sym)) {
rb_hash_aset(h, oj_space_before_sym, rb_str_new2(""));
}
if (!oj_hash_has_key(h, oj_space_sym)) {
rb_hash_aset(h, oj_space_sym, rb_str_new2(" "));
}
if (!oj_hash_has_key(h, oj_object_nl_sym)) {
rb_hash_aset(h, oj_object_nl_sym, rb_str_new2("\n"));
}
if (!oj_hash_has_key(h, oj_array_nl_sym)) {
rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
}
if (Qundef == state_class) {
rb_warn("Oj::Rails.mimic_JSON was called implicitly. "
"Call it explicitly beforehand if you want to remove this warning.");
oj_define_mimic_json(0, NULL, Qnil);
}
rargs[1] = rb_funcall(state_class, oj_new_id, 1, h);
copts.str_rx.head = NULL;
copts.str_rx.tail = NULL;
strcpy(copts.dump_opts.indent_str, " ");
copts.dump_opts.indent_size = (uint8_t)strlen(copts.dump_opts.indent_str);
strcpy(copts.dump_opts.before_sep, "");
copts.dump_opts.before_size = (uint8_t)strlen(copts.dump_opts.before_sep);
strcpy(copts.dump_opts.after_sep, " ");
copts.dump_opts.after_size = (uint8_t)strlen(copts.dump_opts.after_sep);
strcpy(copts.dump_opts.hash_nl, "\n");
copts.dump_opts.hash_size = (uint8_t)strlen(copts.dump_opts.hash_nl);
strcpy(copts.dump_opts.array_nl, "\n");
copts.dump_opts.array_size = (uint8_t)strlen(copts.dump_opts.array_nl);
copts.dump_opts.use = true;
return mimic_generate_core(2, rargs, &copts);
}
Yields to the proc for every element in the obj recursively.
-
obj [Hash|Array] object to walk
-
proc [Proc] to yield to on each element
static VALUE mimic_recurse_proc(VALUE self, VALUE obj) {
rb_need_block();
mimic_walk(Qnil, obj, Qnil);
return Qnil;
}
Loads a Ruby Object from a JSON source that can be either a String or an IO. If Proc is given or a block is provided it is called with each nested element of the loaded Object.
-
source [String|IO]
JSONsource -
proc [Proc] to yield to on each element or nil
Returns [Object] the decoded Object.
static VALUE mimic_load(int argc, VALUE *argv, VALUE self) {
VALUE obj;
VALUE p = Qnil;
obj = oj_compat_load(argc, argv, self);
if (2 <= argc) {
if (rb_cProc == rb_obj_class(argv[1])) {
p = argv[1];
} else if (3 <= argc) {
if (rb_cProc == rb_obj_class(argv[2])) {
p = argv[2];
}
}
}
mimic_walk(Qnil, obj, p);
return obj;
}
Returns [JSON::State] the JSON::State class.
static VALUE mimic_state(VALUE self) {
return state_class;
}
Encode obj as a JSON String. The obj argument must be a Hash, Array, or respond to to_h or to_json. Options other than those listed such as :allow_nan or :max_nesting are ignored.
-
opts [Hash] options
Note JSON.generate does support this even if it is not documented.
Returns [String] generated JSON.
VALUE
oj_mimic_generate(int argc, VALUE *argv, VALUE self) {
struct _options copts = oj_default_options;
copts.str_rx.head = NULL;
copts.str_rx.tail = NULL;
return mimic_generate_core(argc, argv, &copts);
}