Permalink
Browse files

added support for create_id in Oj and in mimic_JSON mode

  • Loading branch information...
Peter Ohler
Peter Ohler committed Apr 18, 2012
1 parent 4477f09 commit c2287f19879ae17e87b69ec668c699e7b90be082
Showing with 73 additions and 12 deletions.
  1. +2 −2 README.md
  2. +2 −2 ext/oj/load.c
  3. +47 −1 ext/oj/oj.c
  4. +1 −0 ext/oj/oj.h
  5. +1 −1 lib/oj/version.rb
  6. +0 −2 notes
  7. +5 −0 test/test_mimic.rb
  8. +15 −4 test/tests.rb
View
@@ -24,9 +24,9 @@ A fast JSON parser and Object marshaller as a Ruby gem.
## <a name="release">Release Notes</a>
-### Release 1.2.4
+### Release 1.2.5
- - Removed all use of math.h to get around CentOS 5.4 compile problem.
+ - Added support for create_id in Oj and in mimic_JSON mode
## <a name="description">Description</a>
View
@@ -475,8 +475,8 @@ read_obj(ParseInfo pi) {
rb_hash_aset(obj, key, val);
}
if ((CompatMode == mode || ObjectMode == mode) &&
- 0 == json_class_name &&
- 0 != ks && 'j' == *ks && 0 == strcmp("json_class", ks) &&
+ 0 == json_class_name && 0 != ks &&
+ 0 != pi->options->create_id && *pi->options->create_id == *ks && 0 == strcmp(pi->options->create_id, ks) &&
T_STRING == rb_type(val)) {
json_class_name = StringValuePtr(val);
}
View
@@ -77,6 +77,7 @@ static VALUE ascii_only_sym;
static VALUE auto_define_sym;
static VALUE circular_sym;
static VALUE compat_sym;
+static VALUE create_id_sym;
static VALUE indent_sym;
static VALUE mode_sym;
static VALUE null_sym;
@@ -101,13 +102,16 @@ Cache oj_attr_cache = 0;
rb_encoding *oj_utf8_encoding = 0;
#endif
+static const char json_class[] = "json_class";
+
struct _Options oj_default_options = {
0, // indent
No, // circular
Yes, // auto_define
No, // sym_key
No, // ascii_only
ObjectMode, // mode
+ json_class, // create_id
0, // dump_opts
};
@@ -121,6 +125,7 @@ static VALUE define_mimic_json(VALUE self);
* - auto_define: [true|false|nil] automatically define classes if they do not exist
* - symbol_keys: [true|false|nil] use symbols instead of strings for hash keys
* - mode: [:object|:strict|:compat|:null] load and dump modes to use for JSON
+ * - create_id: [String|nil] create id for json compatible object encoding, default is 'json_create'
* @return [Hash] all current option settings.
*/
static VALUE
@@ -139,6 +144,8 @@ get_def_opts(VALUE self) {
case ObjectMode:
default: rb_hash_aset(opts, mode_sym, object_sym); break;
}
+ rb_hash_aset(opts, create_id_sym, (0 == oj_default_options.create_id) ? Qnil : rb_str_new2(oj_default_options.create_id));
+
return opts;
}
@@ -158,7 +165,9 @@ get_def_opts(VALUE self) {
* variables if neither is found. The :object mode ignores to_hash()
* and to_json() methods and encodes variables using code internal to
* the Oj gem. The :null mode ignores non-supported Objects and
- * replaces them with a null. @return [nil]
+ * replaces them with a null.
+ * @param [String|nil] :create_id create id for json compatible object encoding
+ * @return [nil]
*/
static VALUE
set_def_opts(VALUE self, VALUE opts) {
@@ -194,6 +203,22 @@ set_def_opts(VALUE self, VALUE opts) {
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null.\n");
}
+ if (Qtrue == rb_funcall(opts, rb_intern("has_key?"), 1, create_id_sym)) {
+ if (0 != oj_default_options.create_id) {
+ if (json_class != oj_default_options.create_id) {
+ xfree((char*)oj_default_options.create_id);
+ }
+ oj_default_options.create_id = 0;
+ }
+ v = rb_hash_lookup(opts, create_id_sym);
+ if (Qnil != v) {
+ size_t len = RSTRING_LEN(v) + 1;
+
+ oj_default_options.create_id = ALLOC_N(char, len);
+ strcpy((char*)oj_default_options.create_id, StringValuePtr(v));
+ }
+ }
+
for (o = ynos; 0 != o->attr; o++) {
if (Qtrue != rb_funcall(opts, rb_intern("has_key?"), 1, o->sym)) {
continue;
@@ -659,6 +684,25 @@ no_op1(VALUE self, VALUE obj) {
return Qnil;
}
+static VALUE
+mimic_create_id(VALUE self, VALUE id) {
+ Check_Type(id, T_STRING);
+
+ if (0 != oj_default_options.create_id) {
+ if (json_class != oj_default_options.create_id) {
+ xfree((char*)oj_default_options.create_id);
+ }
+ oj_default_options.create_id = 0;
+ }
+ if (Qnil != id) {
+ size_t len = RSTRING_LEN(id) + 1;
+
+ oj_default_options.create_id = ALLOC_N(char, len);
+ strcpy((char*)oj_default_options.create_id, StringValuePtr(id));
+ }
+ return id;
+}
+
/* call-seq: mimic_JSON() => Module
*
* Creates the JSON module with methods and classes to mimic the JSON
@@ -679,6 +723,7 @@ define_mimic_json(VALUE self) {
rb_define_module_function(mimic, "parser=", no_op1, 1);
rb_define_module_function(mimic, "generator=", no_op1, 1);
+ rb_define_module_function(mimic, "create_id=", mimic_create_id, 1);
rb_define_module_function(mimic, "dump", mimic_dump, -1);
rb_define_module_function(mimic, "load", mimic_load, -1);
@@ -745,6 +790,7 @@ void Init_oj() {
auto_define_sym = ID2SYM(rb_intern("auto_define")); rb_ary_push(keep, auto_define_sym);
circular_sym = ID2SYM(rb_intern("circular")); rb_ary_push(keep, circular_sym);
compat_sym = ID2SYM(rb_intern("compat")); rb_ary_push(keep, compat_sym);
+ create_id_sym = ID2SYM(rb_intern("create_id")); rb_ary_push(keep, create_id_sym);
indent_sym = ID2SYM(rb_intern("indent")); rb_ary_push(keep, indent_sym);
mode_sym = ID2SYM(rb_intern("mode")); rb_ary_push(keep, mode_sym);
symbol_keys_sym = ID2SYM(rb_intern("symbol_keys")); rb_ary_push(keep, symbol_keys_sym);
View
@@ -95,6 +95,7 @@ typedef struct _Options {
char sym_key; // YesNo
char ascii_only; // YesNo
char mode; // Mode
+ const char *create_id; // 0 or string
DumpOpts dump_opts;
} *Options;
View
@@ -1,5 +1,5 @@
module Oj
# Current version of the module.
- VERSION = '1.2.4'
+ VERSION = '1.2.5'
end
View
2 notes
@@ -6,8 +6,6 @@
- next
- support create_id in mimic
- - allow nil as well
- - add string to options
- optimize read_hex in load.c
- add options for path in fetch
View
@@ -171,6 +171,11 @@ def test_parse_additions
assert_equal(jam, obj)
obj = JSON.parse(json, :create_additions => false)
assert_equal({'json_class' => 'Jam', 'x' => true, 'y' => 58}, obj)
+ json.gsub!('json_class', 'kson_class')
+ JSON.create_id = 'kson_class'
+ obj = JSON.parse(json, :create_additions => true)
+ JSON.create_id = 'json_class'
+ assert_equal(jam, obj)
end
def test_parse_bang
json = %{{"a":1,"b":[true,false]}}
View
@@ -106,7 +106,8 @@ def test0_get_options
:auto_define=>true,
:symbol_keys=>false,
:ascii_only=>false,
- :mode=>:object}, opts)
+ :mode=>:object,
+ :create_id=>'json_class'}, opts)
end
def test0_set_options
@@ -116,18 +117,20 @@ def test0_set_options
:auto_define=>true,
:symbol_keys=>false,
:ascii_only=>false,
- :mode=>:object}
+ :mode=>:object,
+ :create_id=>'json_class'}
o2 = {
:indent=>4,
:circular=>true,
:auto_define=>false,
:symbol_keys=>true,
:ascii_only=>true,
- :mode=>:compat}
+ :mode=>:compat,
+ :create_id=>nil}
o3 = { :indent => 4 }
Oj.default_options = o2
opts = Oj.default_options()
- assert_equal(opts, o2);
+ assert_equal(o2, opts);
Oj.default_options = o3 # see if it throws an exception
Oj.default_options = orig # return to original
end
@@ -339,6 +342,14 @@ def test_json_object_compat
%{{"json_class":"Jeez","y":58,"x":true}} == json)
dump_and_load(obj, false)
end
+ def test_json_object_create_id
+ Oj.default_options = { :mode => :compat, :create_id => 'kson_class' }
+ expected = Jeez.new(true, 58)
+ json = %{{"kson_class":"Jeez","x":true,"y":58}}
+ obj = Oj.load(json)
+ assert_equal(expected, obj)
+ Oj.default_options = { :create_id => 'json_class' }
+ end
def test_json_object_object
obj = Jeez.new(true, 58)
json = Oj.dump(obj, :mode => :object, :indent => 2)

0 comments on commit c2287f1

Please sign in to comment.