Skip to content

Commit e3b2668

Browse files
committedJul 26, 2013
Merge pull request #9 from kuenishi/ignore_null_member_encoding
Ignore null member encoding
2 parents a8381a3 + ba6f498 commit e3b2668

File tree

6 files changed

+76
-10
lines changed

6 files changed

+76
-10
lines changed
 

‎c_src/encoder.c

+23-5
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,21 @@ match_json(ErlNifEnv* env, ERL_NIF_TERM term, State *st){
266266
return 0;
267267
}
268268

269+
static inline int
270+
enc_should_be_ignored(ErlNifEnv* env, ERL_NIF_TERM atom, const EncEntry* entry){
271+
if(!enif_is_atom(env, atom)){
272+
return 0;
273+
}
274+
unsigned i;
275+
for(i=0; i<entry->ignored_len; ++i){
276+
if(enif_is_identical(atom, entry->ignored[i])){
277+
return 1;
278+
}
279+
}
280+
return 0;
281+
}
282+
283+
269284
static inline int
270285
match_record(ErlNifEnv* env, int arity, const ERL_NIF_TERM *tuple, State *st){
271286

@@ -278,12 +293,15 @@ match_record(ErlNifEnv* env, int arity, const ERL_NIF_TERM *tuple, State *st){
278293
unsigned bin_size = 0;
279294
b_putc('{', st);
280295
for(k = 0; k < records[i].arity; k++){
281-
EncField field = fields[fds_offset + k];
282-
bin_size += field.size;
296+
297+
if(!enc_should_be_ignored(env, tuple[k+1], st->records)){
298+
EncField field = fields[fds_offset + k];
299+
bin_size += field.size;
283300
//FIXME {
284-
b_puts(field.size, st->records->bin.data + field.offset, st);
285-
if(!match_term(env, tuple[k+1], st))
286-
return 0;
301+
b_puts(field.size, st->records->bin.data + field.offset, st);
302+
if(!match_term(env, tuple[k+1], st))
303+
return 0;
304+
}
287305
}
288306
b_putc('}', st);
289307
return 1;

‎c_src/jsonx.c

+24-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ enc_rt_dtor(ErlNifEnv* env, void* obj){
88
EncEntry *entry = (EncEntry*)obj;
99
enif_release_binary(&entry->bin);
1010
entry->bin.data = NULL;
11+
if(entry->ignored){
12+
enif_free(entry->ignored);
13+
entry->ignored = NULL;
14+
}
1115
entry = NULL;
1216
}
1317

@@ -73,7 +77,7 @@ make_encoder_resource_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]){
7377
enif_get_uint(env, argv[4], &bin_sz);
7478
PrivData* priv = (PrivData*)enif_priv_data(env);
7579
unsigned resource_sz = enc_resource_size(rs_len, fs_len);
76-
EncEntry *enc_entry = (EncEntry*)enif_alloc_resource(priv->encoder_RSTYPE, resource_sz);
80+
EncEntry *enc_entry = (EncEntry*)enif_alloc_resource(priv->encoder_RSTYPE, resource_sz);
7781
//memset(enc_entry, 0, resource_sz);
7882
enc_entry->records_cnt = rs_len;
7983
enc_entry->fields_cnt = fs_len;
@@ -101,6 +105,7 @@ make_encoder_resource_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]){
101105
i++;
102106
list = tail;
103107
}
108+
104109
list = argv[3];
105110
i = 0;
106111
while(enif_get_list_cell(env, list, &head, &tail)){
@@ -116,6 +121,23 @@ make_encoder_resource_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]){
116121
i++;
117122
list = tail;
118123
}
124+
125+
list = argv[6];
126+
if(!enif_get_list_length(env, list, &(enc_entry->ignored_len)))
127+
goto error;
128+
enc_entry->ignored = (ERL_NIF_TERM*)enif_alloc(enc_entry->ignored_len*sizeof(ERL_NIF_TERM));
129+
i = 0;
130+
while(enif_get_list_cell(env, list, &head, &tail)){
131+
// ignored term should be atoms
132+
if(enif_is_atom(env, head)){
133+
enc_entry->ignored[i] = head;
134+
}else{
135+
enif_free(enc_entry->ignored);
136+
goto error;
137+
}
138+
i++;
139+
list = tail;
140+
}
119141
ERL_NIF_TERM ret = enif_make_resource(env, (void *)enc_entry);
120142
enif_release_resource(enc_entry);
121143
return ret;
@@ -201,7 +223,7 @@ nif_funcs[] = {
201223
{"encode_res", 2, encode_nif}, // with resource
202224
{"decode_opt", 2, decode_nif}, // with options
203225
{"decode_res", 4, decode_nif}, // with options, resource and strict flag
204-
{"make_encoder_resource", 6, make_encoder_resource_nif},
226+
{"make_encoder_resource", 7, make_encoder_resource_nif},
205227
{"make_decoder_resource", 6, make_decoder_resource_nif}
206228
};
207229

‎c_src/jsonx.h

+2
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ typedef struct{
7272
ErlNifBinary bin;
7373
unsigned records_cnt;
7474
unsigned fields_cnt;
75+
ERL_NIF_TERM* ignored;
76+
unsigned ignored_len;
7577
}EncEntry;
7678

7779
static inline EncRecord*

‎examples/records_examples.erl

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ encoder1() ->
88
jsonx:encoder([{person, record_info(fields, person)},
99
{person2, record_info(fields, person2)} ]).
1010

11+
encoder1_ignore() ->
12+
jsonx:encoder([{person, record_info(fields, person)},
13+
{person2, record_info(fields, person2)} ], [{ignore, [null]}]).
14+
1115
decoder1() ->
1216
jsonx:decoder([{person, record_info(fields, person)},
1317
{person2, record_info(fields, person2)}]).

‎src/jsonx.erl

+15-3
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,14 @@
3030
%% </ul>
3131

3232
-module(jsonx).
33-
-export([encode/1, decode/1, decode/2, encoder/1, decoder/1, decoder/2]).
33+
-export([encode/1, decode/1, decode/2,
34+
encoder/1, encoder/2, decoder/1, decoder/2]).
3435
-on_load(init/0).
3536
-define(LIBNAME, jsonx).
3637
-define(APPNAME, jsonx).
3738

39+
-include_lib("eunit/include/eunit.hrl").
40+
3841
%% =================
3942
%% API Encoding JSON
4043
%% =================
@@ -51,8 +54,17 @@ encode(JSON_TERM)->
5154
RECORDS_DESC :: [{tag, [names]}],
5255
ENCODER :: function().
5356
encoder(Records_desc) ->
57+
encoder(Records_desc, []).
58+
59+
%%@doc Build a JSON encoder.
60+
-spec encoder(RECORDS_DESC, OPTIONS) -> ENCODER when
61+
RECORDS_DESC :: [{tag, [names]}],
62+
OPTIONS :: [{ignore, [atom()]}],
63+
ENCODER :: function().
64+
encoder(Records_desc, Options) ->
5465
{Rcnt, Fcnt, Binsz, Records, Fields, Bin} = prepare_enc_desc(Records_desc),
55-
Resource = make_encoder_resource(Rcnt, Fcnt, Records, Fields, Binsz, Bin),
66+
Ignored = proplists:get_value(ignore, Options, []),
67+
Resource = make_encoder_resource(Rcnt, Fcnt, Records, Fields, Binsz, Bin, Ignored),
5668
fun(JSON_TERM) -> encode_res(JSON_TERM, Resource) end.
5769

5870
%% ==================
@@ -116,7 +128,7 @@ decode_opt(_JSON, _FORMAT) ->
116128
decode_res(_JSON_TERM, _FORMAT, _RESOURCE, _STRICT_FLAG) ->
117129
not_loaded(?LINE).
118130

119-
make_encoder_resource(_Rcnt, _Fcnt, _Records, _Fields, _Binsz, _Bin) ->
131+
make_encoder_resource(_Rcnt, _Fcnt, _Records, _Fields, _Binsz, _Bin, _Ignored) ->
120132
not_loaded(?LINE).
121133

122134
make_decoder_resource(_RecCnt, _UKeyCnt, _KeyCnt, _UKeys, _Keys, _Records3) ->

‎test/encode_records_test.erl

+8
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,11 @@ encrec1_test() ->
2020
encrec2_test() ->
2121
F = jsonx:encoder([ {rec, record_info(fields, rec)} ]),
2222
<<"{\"a\": \"x\",\"b\": {\"a\": {\"a\": \"x\",\"b\": \"y\"},\"b\": \"w\"}}">> = F({rec, x, {rec, {rec, x, y}, w}}).
23+
24+
25+
26+
encrec3_test() ->
27+
%%F = jsonx:encoder([ {spam, [a, b, c]} ], [{ignore,null}]),
28+
F = jsonx:encoder([ {spam, [a, b, c]} ], [{ignore, [null, undefined]}]),
29+
<<"{}">> = F({spam, null, null, null}),
30+
<<"{\"a\": \"nall\"}">> = F({spam, nall, null, undefined}).

0 commit comments

Comments
 (0)