summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/json/generator/generator.c44
-rw-r--r--ext/json/generator/generator.h3
-rw-r--r--ext/json/lib/json/common.rb6
-rw-r--r--ext/json/parser/parser.c2
-rw-r--r--ext/json/parser/parser.rl2
-rwxr-xr-xtest/json/json_generator_test.rb11
6 files changed, 62 insertions, 6 deletions
diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c
index efb6b4a0a2..a71acfbb76 100644
--- a/ext/json/generator/generator.c
+++ b/ext/json/generator/generator.c
@@ -16,7 +16,7 @@ static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
i_pack, i_unpack, i_create_id, i_extend, i_key_p,
i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
- i_buffer_initial_length, i_dup, i_script_safe, i_escape_slash;
+ i_buffer_initial_length, i_dup, i_script_safe, i_escape_slash, i_strict;
/*
* Copyright 2001-2004 Unicode, Inc.
@@ -749,6 +749,8 @@ static VALUE cState_configure(VALUE self, VALUE opts)
tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash));
state->script_safe = RTEST(tmp);
}
+ tmp = rb_hash_aref(opts, ID2SYM(i_strict));
+ state->strict = RTEST(tmp);
return self;
}
@@ -784,6 +786,7 @@ static VALUE cState_to_h(VALUE self)
rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
rb_hash_aset(result, ID2SYM(i_script_safe), state->script_safe ? Qtrue : Qfalse);
+ rb_hash_aset(result, ID2SYM(i_strict), state->strict ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
return result;
@@ -1049,6 +1052,8 @@ static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *s
generate_json_bignum(buffer, Vstate, state, obj);
} else if (klass == rb_cFloat) {
generate_json_float(buffer, Vstate, state, obj);
+ } else if (state->strict) {
+ rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(CLASS_OF(obj)));
} else if (rb_respond_to(obj, i_to_json)) {
tmp = rb_funcall(obj, i_to_json, 1, Vstate);
Check_Type(tmp, T_STRING);
@@ -1423,7 +1428,7 @@ static VALUE cState_script_safe(VALUE self)
}
/*
- * call-seq: script_safe=(depth)
+ * call-seq: script_safe=(enable)
*
* This sets whether or not the forward slashes will be escaped in
* the json output.
@@ -1436,6 +1441,37 @@ static VALUE cState_script_safe_set(VALUE self, VALUE enable)
}
/*
+ * call-seq: strict
+ *
+ * If this boolean is false, types unsupported by the JSON format will
+ * be serialized as strings.
+ * If this boolean is true, types unsupported by the JSON format will
+ * raise a JSON::GeneratorError.
+ */
+static VALUE cState_strict(VALUE self)
+{
+ GET_STATE(self);
+ return state->strict ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq: strict=(enable)
+ *
+ * This sets whether or not to serialize types unsupported by the
+ * JSON format as strings.
+ * If this boolean is false, types unsupported by the JSON format will
+ * be serialized as strings.
+ * If this boolean is true, types unsupported by the JSON format will
+ * raise a JSON::GeneratorError.
+ */
+static VALUE cState_strict_set(VALUE self, VALUE enable)
+{
+ GET_STATE(self);
+ state->strict = RTEST(enable);
+ return Qnil;
+}
+
+/*
* call-seq: allow_nan?
*
* Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
@@ -1557,6 +1593,9 @@ void Init_generator(void)
rb_define_alias(cState, "escape_slash", "script_safe");
rb_define_alias(cState, "escape_slash?", "script_safe?");
rb_define_alias(cState, "escape_slash=", "script_safe=");
+ rb_define_method(cState, "strict", cState_strict, 0);
+ rb_define_method(cState, "strict?", cState_strict, 0);
+ rb_define_method(cState, "strict=", cState_strict_set, 1);
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
@@ -1615,6 +1654,7 @@ void Init_generator(void)
i_max_nesting = rb_intern("max_nesting");
i_script_safe = rb_intern("script_safe");
i_escape_slash = rb_intern("escape_slash");
+ i_strict = rb_intern("strict");
i_allow_nan = rb_intern("allow_nan");
i_ascii_only = rb_intern("ascii_only");
i_depth = rb_intern("depth");
diff --git a/ext/json/generator/generator.h b/ext/json/generator/generator.h
index 5e6a228040..1a736b84dd 100644
--- a/ext/json/generator/generator.h
+++ b/ext/json/generator/generator.h
@@ -73,6 +73,7 @@ typedef struct JSON_Generator_StateStruct {
char allow_nan;
char ascii_only;
char script_safe;
+ char strict;
long depth;
long buffer_initial_length;
} JSON_Generator_State;
@@ -153,6 +154,8 @@ static VALUE cState_depth(VALUE self);
static VALUE cState_depth_set(VALUE self, VALUE depth);
static VALUE cState_script_safe(VALUE self);
static VALUE cState_script_safe_set(VALUE self, VALUE depth);
+static VALUE cState_strict(VALUE self);
+static VALUE cState_strict_set(VALUE self, VALUE strict);
static FBuffer *cState_prepare_buffer(VALUE self);
#ifndef ZALLOC
#define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type)))
diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb
index 68ff0efcd0..53b66a9bf6 100644
--- a/ext/json/lib/json/common.rb
+++ b/ext/json/lib/json/common.rb
@@ -3,6 +3,9 @@ require 'json/version'
require 'json/generic_object'
module JSON
+ NOT_SET = Object.new.freeze
+ private_constant :NOT_SET
+
class << self
# :call-seq:
# JSON[object] -> new_array or new_string
@@ -608,7 +611,7 @@ module JSON
# puts File.read(path)
# Output:
# {"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}
- def dump(obj, anIO = nil, limit = nil)
+ def dump(obj, anIO = nil, limit = nil, strict: NOT_SET)
if anIO and limit.nil?
anIO = anIO.to_io if anIO.respond_to?(:to_io)
unless anIO.respond_to?(:write)
@@ -618,6 +621,7 @@ module JSON
end
opts = JSON.dump_default_options
opts = opts.merge(:max_nesting => limit) if limit
+ opts[:strict] = strict if NOT_SET != strict
result = generate(obj, opts)
if anIO
anIO.write result
diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c
index bcd0816f90..57f87432b6 100644
--- a/ext/json/parser/parser.c
+++ b/ext/json/parser/parser.c
@@ -1902,7 +1902,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
json->max_nesting = 100;
json->allow_nan = 0;
json->create_additions = 0;
- json->create_id = rb_funcall(mJSON, i_create_id, 0);
+ json->create_id = Qnil;
json->object_class = Qnil;
json->array_class = Qnil;
json->decimal_class = Qnil;
diff --git a/ext/json/parser/parser.rl b/ext/json/parser/parser.rl
index e6d5d3c152..af190e7500 100644
--- a/ext/json/parser/parser.rl
+++ b/ext/json/parser/parser.rl
@@ -797,7 +797,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
json->max_nesting = 100;
json->allow_nan = 0;
json->create_additions = 0;
- json->create_id = rb_funcall(mJSON, i_create_id, 0);
+ json->create_id = Qnil;
json->object_class = Qnil;
json->array_class = Qnil;
json->decimal_class = Qnil;
diff --git a/test/json/json_generator_test.rb b/test/json/json_generator_test.rb
index 1bf4912ec7..46cbf9c7f7 100755
--- a/test/json/json_generator_test.rb
+++ b/test/json/json_generator_test.rb
@@ -150,6 +150,7 @@ EOT
:buffer_initial_length => 1024,
:depth => 0,
:script_safe => false,
+ :strict => false,
:indent => " ",
:max_nesting => 100,
:object_nl => "\n",
@@ -167,6 +168,7 @@ EOT
:buffer_initial_length => 1024,
:depth => 0,
:script_safe => false,
+ :strict => false,
:indent => "",
:max_nesting => 100,
:object_nl => "",
@@ -184,6 +186,7 @@ EOT
:buffer_initial_length => 1024,
:depth => 0,
:script_safe => false,
+ :strict => false,
:indent => "",
:max_nesting => 0,
:object_nl => "",
@@ -336,7 +339,13 @@ EOT
def test_json_generate
assert_raise JSON::GeneratorError do
- assert_equal true, generate(["\xea"])
+ generate(["\xea"])
+ end
+ end
+
+ def test_json_generate_unsupported_types
+ assert_raise JSON::GeneratorError do
+ generate(Object.new, strict: true)
end
end