ibireme / yyjson

The fastest JSON library in C
https://ibireme.github.io/yyjson/doc/doxygen/html/
MIT License
3.04k stars 262 forks source link

Public API to allow building values without allocation (no mut_doc APIs) #87

Closed andrei-datcu closed 2 years ago

andrei-datcu commented 2 years ago

Is your feature request related to a problem? Please describe. It would be nice if we could have public APIs to initialize yyjson_mut_val stack objects that we could then pass along to yyjson_mut_obj_add / yyjson_mut_arr_append. That's because most of the time, the responses are simple and static enough for this to work.

Describe the solution you'd like Say for instance I want to build:

{code: 5, params: [1, "error-msg"]};

it would be nice if I could do it with no allocations

yyjson_mut_val root, code_key, code_val, params_key, params_arr, one, msg;

/*
 * start of missing API
 */
 yyjson_mut_set_obj(&root);
 yyjson_mut_set_str(&code_key, "code_key");
 yyjson_mut_set_int(&code_val, 5);
 yyjson_mut_set_str(&params_key, "params");
 yyjson_mut_set_arr(&params_arr);
 yyjson_mut_set_int(&one, 1);
 yyjson_mut_set_str(&msg, "error-msg");
 /*
  * end of missing APIs
  */

 // we can already do those
 yyjson_mut_obj_add(&root, &code_key, &code_val);
 yyjson_mut_obj_add(&root, &params_key, &params);
 yyjson_mut_arr_append(&params, &one);
 yyjson_mut_arr_append(&params, &msg);

 char buf[100];
 // ....
 yyjson_mut_val_write_opts(&root, &alc ....);

Describe alternatives you've considered I guess tags could be set manually on the struct instances, but tags are advertised as being part of the private API.

ibireme commented 2 years ago

I added some functions as you suggested: https://github.com/ibireme/yyjson/commit/ee9e6d5d3bde4a26b78e9cfd596dd28d231266fa, and here is an example:

// build JSON on stack
yyjson_mut_val root, code_key, code, msg_key, msg, arr_key, arr, n1, n2;
yyjson_mut_set_obj(&root);
yyjson_mut_set_str(&code_key, "code");
yyjson_mut_set_int(&code, 200);
yyjson_mut_set_str(&msg_key, "msg");
yyjson_mut_set_str(&msg, "success");
yyjson_mut_set_str(&arr_key, "arr");
yyjson_mut_set_arr(&arr);
yyjson_mut_set_bool(&n1, true);
yyjson_mut_set_bool(&n2, false);

yyjson_mut_obj_add(&root, &code_key, &code);
yyjson_mut_obj_add(&root, &msg_key, &msg);
yyjson_mut_obj_add(&root, &arr_key, &arr);
yyjson_mut_arr_append(&arr, &n1);
yyjson_mut_arr_append(&arr, &n2);

char buf[256];
yyjson_alc alc;
yyjson_alc_pool_init(&alc, buf, sizeof(buf));
char *json = yyjson_mut_val_write_opts(&root, 0, &alc, NULL, NULL);
// {"code":200,"msg":"success","arr":[true,false]}
andrei-datcu commented 2 years ago

Well, this is outstanding. Thanks a bunch. Will give it a spin and report back.

zestzone007 commented 2 years ago

back that is a good idea, I am also looking forward to it.

andrei-datcu commented 2 years ago

This is working as advertised, great work @ibireme. The writing part of https://github.com/ibireme/yyjson/issues/33 can be marked as done.