summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Barrié <[email protected]>2025-01-20 11:12:09 +0100
committerJean Boussier <[email protected]>2025-01-20 14:20:55 +0100
commite8676cada82ed9947502b416eaa948258a62d7b9 (patch)
tree05dbf50a935789222337d04b1edc230b296de02b
parentba44e92573f5fdd23d29cfb49d8afe78287d5f79 (diff)
[ruby/json] Introduce JSON::Fragment
https://github.com/ruby/json/commit/9e3500f345 Co-authored-by: Jean Boussier <[email protected]>
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/12602
-rw-r--r--ext/json/generator/generator.c18
-rw-r--r--ext/json/lib/json/common.rb6
-rwxr-xr-xtest/json/json_generator_test.rb5
3 files changed, 28 insertions, 1 deletions
diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c
index 5006b7853e..62c0c420cc 100644
--- a/ext/json/generator/generator.c
+++ b/ext/json/generator/generator.c
@@ -27,7 +27,7 @@ typedef struct JSON_Generator_StateStruct {
#define RB_UNLIKELY(cond) (cond)
#endif
-static VALUE mJSON, cState, mString_Extend, eGeneratorError, eNestingError, Encoding_UTF_8;
+static VALUE mJSON, cState, cFragment, mString_Extend, eGeneratorError, eNestingError, Encoding_UTF_8;
static ID i_to_s, i_to_json, i_new, i_pack, i_unpack, i_create_id, i_extend, i_encode;
static ID sym_indent, sym_space, sym_space_before, sym_object_nl, sym_array_nl, sym_max_nesting, sym_allow_nan,
@@ -68,6 +68,7 @@ static void generate_json_integer(FBuffer *buffer, struct generate_json_data *da
static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
+static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj);
static int usascii_encindex, utf8_encindex, binary_encindex;
@@ -971,6 +972,13 @@ static void generate_json_float(FBuffer *buffer, struct generate_json_data *data
fbuffer_append_str(buffer, tmp);
}
+static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
+{
+ VALUE fragment = RSTRUCT_GET(obj, 0);
+ Check_Type(fragment, T_STRING);
+ fbuffer_append_str(buffer, fragment);
+}
+
static void generate_json(FBuffer *buffer, struct generate_json_data *data, JSON_Generator_State *state, VALUE obj)
{
VALUE tmp;
@@ -1010,6 +1018,10 @@ static void generate_json(FBuffer *buffer, struct generate_json_data *data, JSON
if (klass != rb_cFloat) goto general;
generate_json_float(buffer, data, state, obj);
break;
+ case T_STRUCT:
+ if (klass != cFragment) goto general;
+ generate_json_fragment(buffer, data, state, obj);
+ break;
default:
general:
if (state->strict) {
@@ -1546,6 +1558,10 @@ void Init_generator(void)
rb_require("json/common");
mJSON = rb_define_module("JSON");
+
+ rb_global_variable(&cFragment);
+ cFragment = rb_const_get(mJSON, rb_intern("Fragment"));
+
VALUE mExt = rb_define_module_under(mJSON, "Ext");
VALUE mGenerator = rb_define_module_under(mExt, "Generator");
diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb
index 3c85ef0655..8a000aa359 100644
--- a/ext/json/lib/json/common.rb
+++ b/ext/json/lib/json/common.rb
@@ -167,6 +167,12 @@ module JSON
# system. Usually this means that the iconv library is not installed.
class MissingUnicodeSupport < JSONError; end
+ Fragment = Struct.new(:json) do
+ def to_json(state = nil)
+ json
+ end
+ end
+
module_function
# :call-seq:
diff --git a/test/json/json_generator_test.rb b/test/json/json_generator_test.rb
index 8dd3913d62..824de2c1a6 100755
--- a/test/json/json_generator_test.rb
+++ b/test/json/json_generator_test.rb
@@ -661,4 +661,9 @@ class JSONGeneratorTest < Test::Unit::TestCase
def test_nonutf8_encoding
assert_equal("\"5\u{b0}\"", "5\xb0".dup.force_encoding(Encoding::ISO_8859_1).to_json)
end
+
+ def test_fragment
+ fragment = JSON::Fragment.new(" 42")
+ assert_equal '{"number": 42}', JSON.generate({ number: fragment })
+ end
end