From cdb1a73615415e88ac8ef1b2eeec216fe72b9794 Mon Sep 17 00:00:00 2001 From: "Yichun Zhang (agentzh)" Date: Tue, 18 Feb 2014 14:33:37 -0800 Subject: feature: applied Jiale Zhi's patch to add the new config function encode_empty_table_as_object so that we can encode empty Lua tables into empty JSON arrays. --- lua_cjson.c | 14 +++++++++++- tests/TestLua.pm | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/agentzh.t | 41 +++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 tests/TestLua.pm create mode 100644 tests/agentzh.t diff --git a/lua_cjson.c b/lua_cjson.c index c14a1c5..97f2350 100644 --- a/lua_cjson.c +++ b/lua_cjson.c @@ -68,6 +68,7 @@ #define DEFAULT_DECODE_INVALID_NUMBERS 1 #define DEFAULT_ENCODE_KEEP_BUFFER 1 #define DEFAULT_ENCODE_NUMBER_PRECISION 14 +#define DEFAULT_ENCODE_EMPTY_TABLE_AS_OBJECT 1 #ifdef DISABLE_INVALID_NUMBERS #undef DEFAULT_DECODE_INVALID_NUMBERS @@ -124,6 +125,7 @@ typedef struct { int encode_invalid_numbers; /* 2 => Encode as "null" */ int encode_number_precision; int encode_keep_buffer; + int encode_empty_table_as_object; int decode_invalid_numbers; int decode_max_depth; @@ -300,6 +302,14 @@ static int json_cfg_encode_number_precision(lua_State *l) return json_integer_option(l, 1, &cfg->encode_number_precision, 1, 14); } +/* Configures how to treat empty table when encode lua table */ +static int json_cfg_encode_empty_table_as_object(lua_State *l) +{ + json_config_t *cfg = json_arg_init(l, 1); + + return json_enum_option(l, 1, &cfg->encode_empty_table_as_object, NULL, 1); +} + /* Configures JSON encoding buffer persistence */ static int json_cfg_encode_keep_buffer(lua_State *l) { @@ -390,6 +400,7 @@ static void json_create_config(lua_State *l) cfg->decode_invalid_numbers = DEFAULT_DECODE_INVALID_NUMBERS; cfg->encode_keep_buffer = DEFAULT_ENCODE_KEEP_BUFFER; cfg->encode_number_precision = DEFAULT_ENCODE_NUMBER_PRECISION; + cfg->encode_empty_table_as_object = DEFAULT_ENCODE_EMPTY_TABLE_AS_OBJECT; #if DEFAULT_ENCODE_KEEP_BUFFER > 0 strbuf_init(&cfg->encode_buf, 0); @@ -685,7 +696,7 @@ static void json_append_data(lua_State *l, json_config_t *cfg, current_depth++; json_check_encode_depth(l, cfg, current_depth, json); len = lua_array_length(l, cfg, json); - if (len > 0) + if (len > 0 || (len == 0 && !cfg->encode_empty_table_as_object)) json_append_array(l, cfg, current_depth, json, len); else json_append_object(l, cfg, current_depth, json); @@ -1352,6 +1363,7 @@ static int lua_cjson_new(lua_State *l) luaL_Reg reg[] = { { "encode", json_encode }, { "decode", json_decode }, + { "encode_empty_table_as_object", json_cfg_encode_empty_table_as_object }, { "encode_sparse_array", json_cfg_encode_sparse_array }, { "encode_max_depth", json_cfg_encode_max_depth }, { "decode_max_depth", json_cfg_decode_max_depth }, diff --git a/tests/TestLua.pm b/tests/TestLua.pm new file mode 100644 index 0000000..cd22d83 --- /dev/null +++ b/tests/TestLua.pm @@ -0,0 +1,70 @@ +package TestLua; + +use Test::Base -Base; +use IPC::Run3; +use Cwd; + +use Test::LongString; + +our @EXPORT = qw( run_tests ); + +$ENV{LUA_CPATH} = "../?.so;;"; +$ENV{LUA_PATH} = "../lua/?.lua;;"; +#$ENV{LUA_PATH} = ($ENV{LUA_PATH} || "" ) . ';' . getcwd . "/runtime/?.lua" . ';;'; + +sub run_test ($) { + my $block = shift; + #print $json_xs->pretty->encode(\@new_rows); + #my $res = #print $json_xs->pretty->encode($res); + my $name = $block->name; + + my $lua = $block->lua or + die "No --- lua specified for test $name\n"; + + my $luafile = "test_case.lua"; + + open my $fh, ">$luafile" or + die "Cannot open $luafile for writing: $!\n"; + + print $fh $lua; + close $fh; + + my ($res, $err); + + my @cmd; + + if ($ENV{TEST_LUA_USE_VALGRIND}) { + @cmd = ('valgrind', '-q', '--leak-check=full', 'lua', 'test_case.lua'); + } else { + @cmd = ('lua', 'test_case.lua'); + } + + run3 \@cmd, undef, \$res, \$err; + my $rc = $?; + + #warn "res:$res\nerr:$err\n"; + + if (defined $block->err) { + $err =~ /.*:.*:.*: (.*\s)?/; + $err = $1; + is $err, $block->err, "$name - err expected"; + + } elsif ($rc) { + die "Failed to execute --- lua for test $name: $err\n"; + + } else { + #is $res, $block->out, "$name - output ok"; + is $res, $block->out, "$name - output ok"; + } + + is $rc, ($block->exit || 0), "$name - exit code ok"; + #unlink 'test_case.lua' or warn "could not delete \'test_case.lua\':$!"; +} + +sub run_tests () { + for my $block (blocks()) { + run_test($block); + } +} + +1; diff --git a/tests/agentzh.t b/tests/agentzh.t new file mode 100644 index 0000000..aeebd67 --- /dev/null +++ b/tests/agentzh.t @@ -0,0 +1,41 @@ +use TestLua; + +plan tests => 2 * blocks(); + +run_tests(); + +__DATA__ + +=== TEST 1: empty tables as objects +--- lua +local cjson = require "cjson" +print(cjson.encode({})) +print(cjson.encode({dogs = {}})) +--- out +{} +{"dogs":{}} + + + +=== TEST 2: empty tables as arrays +--- lua +local cjson = require "cjson" +cjson.encode_empty_table_as_object(false) +print(cjson.encode({})) +print(cjson.encode({dogs = {}})) +--- out +[] +{"dogs":[]} + + + +=== TEST 3: empty tables as objects (explicit) +--- lua +local cjson = require "cjson" +cjson.encode_empty_table_as_object(true) +print(cjson.encode({})) +print(cjson.encode({dogs = {}})) +--- out +{} +{"dogs":{}} + -- cgit v1.2.3-55-g6feb