Skip to content

Commit

Permalink
Merge pull request #626 from casperisfine/pretty-generate-empty-colle…
Browse files Browse the repository at this point in the history
…ctions

pretty_generate: don't apply object_nl / array_nl for empty containers
  • Loading branch information
byroot authored Oct 24, 2024
2 parents 843195b + b2c4480 commit 7a8c0b7
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 2 deletions.
14 changes: 14 additions & 0 deletions ext/json/ext/generator/generator.c
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,13 @@ static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
if (max_nesting != 0 && depth > max_nesting) {
rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
}

if (RHASH_SIZE(obj) == 0) {
fbuffer_append(buffer, "{}", 2);
--state->depth;
return;
}

fbuffer_append_char(buffer, '{');

arg.buffer = buffer;
Expand Down Expand Up @@ -709,6 +716,13 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
if (max_nesting != 0 && depth > max_nesting) {
rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
}

if (RARRAY_LEN(obj) == 0) {
fbuffer_append(buffer, "[]", 2);
--state->depth;
return;
}

fbuffer_append_char(buffer, '[');
if (RB_UNLIKELY(state->array_nl)) fbuffer_append(buffer, state->array_nl, state->array_nl_len);
for(i = 0; i < RARRAY_LEN(obj); i++) {
Expand Down
12 changes: 12 additions & 0 deletions java/src/json/ext/Generator.java
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,12 @@ void generate(Session session, RubyArray object, ByteList buffer) {
GeneratorState state = session.getState();
int depth = state.increaseDepth();

if (object.isEmpty()) {
buffer.append("[]".getBytes());
state.decreaseDepth();
return;
}

ByteList indentUnit = state.getIndent();
byte[] shift = Utils.repeat(indentUnit, depth);

Expand Down Expand Up @@ -327,6 +333,12 @@ void generate(final Session session, RubyHash object,
final GeneratorState state = session.getState();
final int depth = state.increaseDepth();

if (object.isEmpty()) {
buffer.append("{}".getBytes());
state.decreaseDepth();
return;
}

final ByteList objectNl = state.getObjectNl();
final byte[] indent = Utils.repeat(state.getIndent(), depth);
final ByteList spaceBefore = state.getSpaceBefore();
Expand Down
17 changes: 15 additions & 2 deletions lib/json/pure/generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -399,9 +399,15 @@ def json_shift(state)
end

def json_transform(state)
depth = state.depth += 1

if empty?
state.depth -= 1
return '{}'
end

delim = ",#{state.object_nl}"
result = +"{#{state.object_nl}"
depth = state.depth += 1
first = true
indent = !state.object_nl.empty?
each { |key, value|
Expand Down Expand Up @@ -441,14 +447,21 @@ def to_json(state = nil, *)
private

def json_transform(state)
depth = state.depth += 1

if empty?
state.depth -= 1
return '[]'
end

result = '['.dup
if state.array_nl.empty?
delim = ","
else
result << state.array_nl
delim = ",#{state.array_nl}"
end
depth = state.depth += 1

first = true
indent = !state.array_nl.empty?
each { |value|
Expand Down
7 changes: 7 additions & 0 deletions test/json/json_generator_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,17 @@ def test_dump_strict

def test_generate_pretty
json = pretty_generate({})
assert_equal('{}', json)

json = pretty_generate({1=>{}, 2=>[], 3=>4})
assert_equal(<<'EOT'.chomp, json)
{
"1": {},
"2": [],
"3": 4
}
EOT

json = pretty_generate(@hash)
# hashes aren't (insertion) ordered on every ruby implementation
# assert_equal(@json3, json)
Expand Down

0 comments on commit 7a8c0b7

Please sign in to comment.