Closed MadDogMayCry0 closed 2 years ago
Sorry for the bad doc...
To iterate over the key-value pairs of an existing object (your first object), you can use iterator API: https://github.com/ibireme/yyjson/blob/master/doc/API.md#json-object-iterator-api
To add a key-value pair to an object (your second object), you can use yyjson_mut_obj_add(obj, key, val)
or yyjson_mut_obj_put(obj, key, val)
:
https://github.com/ibireme/yyjson/blob/master/doc/API.md#mutable-json-object-modification-api
Sorry for the bad doc...
To iterate over the key-value pairs of an existing object (your first object), you can use iterator API: https://github.com/ibireme/yyjson/blob/master/doc/API.md#json-object-iterator-api
To add a key-value pair to an object (your second object), you can use
yyjson_mut_obj_add(obj, key, val)
oryyjson_mut_obj_put(obj, key, val)
: https://github.com/ibireme/yyjson/blob/master/doc/API.md#mutable-json-object-modification-api
Please, can you write some example? In cJSON i create two objects and then addOne to AnotherOne. How to do this in your lib?
cJSON *root = cJSON_CreateObject();
cJSON *item = cJSON_CreateObject();
cJSON_AddStringToObject(item,"type","toy");
cJSON_AddStringToObject(item,"ip","myip");
cJSON_AddItemToObject(root, "0", item);
But in case you described above, i can only put a key and set his value, but how to set subItem with his own subKeys (Object)? @ibireme
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
yyjson_mut_val *root = yyjson_mut_obj(doc);
yyjson_mut_doc_set_root(doc, root);
yyjson_mut_obj_add_str(doc, root, "type", "toy");
yyjson_mut_obj_add_str(doc, root, "ip", "myip");
...
Here is the complete example code:
// create a doc to manage memory allocation
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
// same as cJSON
yyjson_mut_val *root = yyjson_mut_obj(doc);
yyjson_mut_val *item = yyjson_mut_obj(doc);
yyjson_mut_obj_add_strcpy(doc, item, "type", "toy");
yyjson_mut_obj_add_strcpy(doc, item, "ip", "myip");
yyjson_mut_obj_add_val(doc, root, "0", item);
// set doc root, write to string
yyjson_mut_doc_set_root(doc, root);
char *json = yyjson_mut_write(doc, YYJSON_WRITE_PRETTY, NULL);
printf("%s\n", json);
// free all memory
yyjson_mut_doc_free(doc);
free(json);
Thank you veary much!
@ibireme
UPD2
int i = 0;
// create a doc to manage memory allocation
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
// same as cJSON
yyjson_mut_val *root = yyjson_mut_obj(doc);
while(true){
const char cnt[5];itoa(i,&cnt,10);
yyjson_mut_val *item = yyjson_mut_obj(doc);
yyjson_mut_obj_add_strcpy(doc, item, "type", "toy");
yyjson_mut_obj_add_strcpy(doc, item, "ip", "myip");
yyjson_mut_obj_add_val(doc, root, cnt, item);
// set doc root, write to string
yyjson_mut_doc_set_root(doc, root);
char *json = yyjson_mut_write(doc, YYJSON_WRITE_PRETTY, NULL);
printf("%s\n", json);
free(json);
// free all memory
// yyjson_mut_doc_free(doc);
vTaskDelay(1000 / portTICK_PERIOD_MS);
i++;
}
strange, but each new key updates all old keys to his own =)
{
"4": {
"type": "toy",
"ip": "myip"
},
"4": {
"type": "toy",
"ip": "myip"
},
"4": {
"type": "toy",
"ip": "myip"
},
"4": {
"type": "toy",
"ip": "myip"
},
"4": {
"type": "toy",
"ip": "myip"
}
}
UPD No, it does! Will try some tests. =) Com;ilation on Tensilica Xtensa LX6 (dual core cpu) This one https://en.wikipedia.org/wiki/ESP32 Thx you again!
It's seems to be this library no wanna be compilled for ESP-IDF @ VSCODE over cmake v4 for esp32 chip :(
main/app.c:59: undefined
reference to `yyjson_mut_doc_free'
collect2.exe: error: ld returned 1 exit status
@ibireme
UPD2
int i = 0;
// create a doc to manage memory allocation
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
// same as cJSON
yyjson_mut_val *root = yyjson_mut_obj(doc);
while(true){
const char cnt[5];itoa(i,&cnt,10);
yyjson_mut_val *item = yyjson_mut_obj(doc);
yyjson_mut_obj_add_strcpy(doc, item, "type", "toy");
yyjson_mut_obj_add_strcpy(doc, item, "ip", "myip");
yyjson_mut_obj_add_val(doc, root, cnt, item);
// set doc root, write to string
yyjson_mut_doc_set_root(doc, root);
char *json = yyjson_mut_write(doc, YYJSON_WRITE_PRETTY, NULL);
printf("%s\n", json);
free(json);
// free all memory
// yyjson_mut_doc_free(doc);
vTaskDelay(1000 / portTICK_PERIOD_MS);
i++;
}
strange, but each new key updates all old keys to his own =)
{
"4": {
"type": "toy",
"ip": "myip"
},
"4": {
"type": "toy",
"ip": "myip"
},
"4": {
"type": "toy",
"ip": "myip"
},
"4": {
"type": "toy",
"ip": "myip"
},
"4": {
"type": "toy",
"ip": "myip"
}
}
The string is not copied by default , you need to use the API with the cpy
to copy the value:
yyjson_mut_val *key = yyjson_mut_strcpy(doc, cnt);
yyjson_mut_obj_add(doc, key, item);
The documentation here is not clear enough, I'll update it later.
@ibireme
int i = 0;
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
yyjson_mut_val *root = yyjson_mut_obj(doc);
while(true){
char cnt[5];itoa(i,&cnt,10);
yyjson_mut_val *item = yyjson_mut_obj(doc);
yyjson_mut_obj_add_str(doc, item, "type", "toy");
yyjson_mut_obj_add_str(doc, item, "ip", "myip");
yyjson_mut_val *key = yyjson_mut_strcpy(doc, cnt);
yyjson_mut_obj_add(doc, key, item);
yyjson_mut_doc_set_root(doc, root);
char *json = yyjson_mut_write(doc, YYJSON_WRITE_PRETTY, NULL);
printf("%s\n", json);
free(json);
vTaskDelay(1000 / portTICK_PERIOD_MS);
i++;
}
now i have
{}
in output string :(
My mistake, that line should be: yyjson_mut_obj_add(root, key, item);
.
I've tested and the output should be OK now.
@ibireme
My mistake, that line should be:
yyjson_mut_obj_add(root, key, item);
. I've tested and the output should be OK now.
Some tests:
cJSON_AddStringToObject(item,"type", "toys");
cJSON_AddStringToObject(item,"ip","Hello, it's me Mario :)");
cJSON_AddItemToObject(root, cnt, item);
adding key value's pair as above:
YYJSON - 4uS (WOW)
cJSON - 65uS veary slow...
my ram is 225kb max objects for:
cJSON 1573
YYJSON 1359
So, speed needs more ram.
Ok, conclusion on this moment looks like:
int i = 0;
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
yyjson_mut_val *root = yyjson_mut_obj(doc);
while(true){
char cnt[5];itoa(i,&cnt,10);
yyjson_mut_val *item = yyjson_mut_obj(doc);
yyjson_mut_obj_add_str(doc, item, "type", "toy");
yyjson_mut_obj_add_str(doc, item, "ip", "myip");
yyjson_mut_val *key = yyjson_mut_strcpy(doc, cnt);
yyjson_mut_obj_add(root, key, item);
yyjson_mut_doc_set_root(doc, root);
char *json = yyjson_mut_write(doc, YYJSON_WRITE_PRETTY, NULL);
printf("%s\n", json);
free(json);
i++;
}
For example, how to get "toy" from "0"->"type"->"toy"? in a foreach cycle?
"0": {
"type": "toy",
"ip": "myip"
}
How to convert yyjson_val to char[] ?
size_t idx, max;
yyjson_val *key_, *val;
yyjson_obj_foreach(root, idx, max, key_, val){
printf("key:%s - val:%s",key_,val);
}
format '%s' expects argument of type 'char *', but argument 7 has type 'yyjson_val *'
To get the content from val, you can use yyjson_get_xxx(val)
:
const char *json = "{\"0\":{\"type\":\"toy0\"},\"1\":{\"type\":\"toy1\"}}";
yyjson_doc *doc = yyjson_read(json, strlen(json), 0);
yyjson_val *root = yyjson_doc_get_root(doc);
usize idx, max;
yyjson_val *key, *val;
yyjson_obj_foreach(root, idx, max, key, val) {
printf("key: %s\n", yyjson_get_str(key)); // "0", "1"
yyjson_val *type = yyjson_obj_get(val, "type");
printf("type: %s\n", yyjson_get_str(type)); // "toy0", "toy1"
}
@ibireme
To get the content from val, you can use
yyjson_get_xxx(val)
:const char *json = "{\"0\":{\"type\":\"toy0\"},\"1\":{\"type\":\"toy1\"}}"; yyjson_doc *doc = yyjson_read(json, strlen(json), 0); yyjson_val *root = yyjson_doc_get_root(doc); usize idx, max; yyjson_val *key, *val; yyjson_obj_foreach(root, idx, max, key, val) { printf("key: %s\n", yyjson_get_str(key)); // "0", "1" yyjson_val *type = yyjson_obj_get(val, "type"); printf("type: %s\n", yyjson_get_str(type)); // "toy0", "toy1" }
Ok, i see you use new string, but i want to use current Objects in ram. I doing same, but get PANIC
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
yyjson_mut_val *root = yyjson_mut_obj(doc);
while(true){
char cnt[5];itoa(i,&cnt,10);
yyjson_mut_val *key = yyjson_mut_str(doc, cnt);
yyjson_mut_val *item = yyjson_mut_obj(doc);
yyjson_mut_obj_add_str(doc, item, "type", "toy");
yyjson_mut_obj_add_str(doc, item, "ip", "Hello, it's me Mario :)");
if(yyjson_mut_obj_add(root, key, item)){
usize idx, max;
yyjson_val *key, *val;
yyjson_obj_foreach(root, idx, max, key, val) {
printf("key: %s\n", yyjson_get_str(key)); // "0", "1"
yyjson_val *type = yyjson_obj_get(val, "type");
printf("type: %s\n", yyjson_get_str(type)); // "toy0", "toy1"
}
}
}
with this i get nothing in foreach (0 cycles)
yyjson_val *root = yyjson_doc_get_root(doc);
Help =(
All mutable values should be called with mut
function, otherwise there will be a type mismatch warning.
The inner loop should be:
usize idx, max;
yyjson_mut_val *key_i, *val_i;
yyjson_mut_obj_foreach(root, idx, max, key_i, val_i) {
printf("key: %s\n", yyjson_mut_get_str(key_i)); // "0", "1"
yyjson_mut_val *type = yyjson_mut_obj_get(val_i, "type");
printf("type: %s\n", yyjson_mut_get_str(type)); // "toy0", "toy1"
}
@ibireme i try to remove key in root
yyjson_mut_val *test = yyjson_mut_obj_get(root, "0");
yyjson_mut_obj_clear(test);
or
yyjson_mut_obj_remove(root, "0");
Without success.. I promise to make simple examples based on your answers =)
Try this
yyjson_mut_obj_remove_str(root, "0");
or
yyjson_mut_obj_remove(root, yyjson_mut_str(doc, "0"));
When passing in the wrong type, you should get a incompatible pointer types passing
warning in compile log.
It's works. I'll be back later and post simple examples that someone can use in future! Thank you! Don't close issue pls, maby i have more question about sub objects and sub arrays.
@ibireme I did some tests and i have something wrong.
It seems that the method that deletes the string does not release memory, or I'm doing something wrong. After ten deletion cycles, the memory does not return to its original value, but continues to be consumed.
int i = 0;
int d = 15;
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
yyjson_mut_val *root = yyjson_mut_obj(doc);
while(true){
char cnt[5];itoa(i,&cnt,10);
if(i<=15){
yyjson_mut_val *obj = yyjson_mut_strcpy(doc, cnt);
yyjson_mut_val *item = yyjson_mut_obj(doc);
yyjson_mut_obj_add_str(doc, item, "name", "djfhsdkjafhj sadhlfjhsaldjf hlskjad fhljksadhf lkjsadhfl jhsadlkjf hlsakdjf hlkjsadh flkjasdhf lkjsahdlfjk hsalkdjfh");
yyjson_mut_obj_add_str(doc, item, "type", "dfkjsdkfj lsdkjflk sjdlfjsdl jflsdkjflksjdfl kjsdlfkj lsdkfj lskdfj");
yyjson_mut_obj_add(root, obj, item);
i++;
}
else{
char cnt[5];itoa(d,&cnt,10);
yyjson_mut_obj_remove_str(root,cnt);
if(d==0){
i=0;
d=16;
}
d--;
}
}
Before cycles 359457
After 10 deliting cycles 317256
After 40 deliting cycles 249144
It seems that the method that deletes the string does not release memory, or I'm doing something wrong. After ten deletion cycles, the memory does not return to its original value, but continues to be consumed.
This behavior is documented: https://github.com/ibireme/yyjson/blob/master/doc/API.md#create-json-document
@ibireme
It seems that the method that deletes the string does not release memory, or I'm doing something wrong. After ten deletion cycles, the memory does not return to its original value, but continues to be consumed.
This behavior is documented: https://github.com/ibireme/yyjson/blob/master/doc/API.md#create-json-document
How, then, to keep a constantly changing dynamic object? I need to keep a dynamically changing object in memory throughout the whole time :(
How, then, to keep a constantly changing dynamic object? I need to keep a dynamically changing object in memory throughout the whole time :(
You can use yyjson_mut_doc_mut_copy()
to create a copy and then free the old doc.
But as the documentation says, yyjson_mut_doc
is more suitable for write-once, than mutation of an existing document.
How, then, to keep a constantly changing dynamic object? I need to keep a dynamically changing object in memory throughout the whole time :(
You can use
yyjson_mut_doc_mut_copy()
to create a copy and then free the old doc. But as the documentation says,yyjson_mut_doc
is more suitable for write-once, than mutation of an existing document.
It's any other way to use something else instead of mut in my case?
How, then, to keep a constantly changing dynamic object? I need to keep a dynamically changing object in memory throughout the whole time :(
You can use
yyjson_mut_doc_mut_copy()
to create a copy and then free the old doc. But as the documentation says,yyjson_mut_doc
is more suitable for write-once, than mutation of an existing document.It's any other way to use something else instead of mut in my case?
You can use your own data structures to hold your values, and then create the JSON doc, serialize to string, free it all at once when you need a JSON string.
@ibireme Or we can get new function
yyjson_doc_update_size(doc);
=)
It's hard to do that, for example:
┌───────────────────────────────────────────────────┐
│0 toy myip 1 toy1 myip1 │
└▲─▲────────────────────────────────────────────────┘
│ │
└─┼──── yyjson_mut_val *val1 = yyjson_mut_strcpy(doc, "0");
│
└──── yyjson_mut_val *val2 = yyjson_mut_strcpy(doc, "toy");
Multiple strings are stored in one contiguous memory area. When you try to free val1
, the memory of string is not actually freed.
@ibireme Ok, let me going through mut_doc_free way. I try to
int i = 0;
int d = 15;
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
yyjson_mut_val *root = yyjson_mut_obj(doc);
while(true){
char cnt[5];itoa(i,&cnt,10);
if(i<=15){
yyjson_mut_val *obj = yyjson_mut_strcpy(doc, cnt);
yyjson_mut_val *item = yyjson_mut_obj(doc);
yyjson_mut_obj_add_str(doc, item, "name", "djfhsdkjafhj sadhlfjhsaldjf hlskjad fhljksadhf lkjsadhfl jhsadlkjf hlsakdjf hlkjsadh flkjasdhf lkjsahdlfjk hsalkdjfh");
yyjson_mut_obj_add_str(doc, item, "type", "dfkjsdkfj lsdkjflk sjdlfjsdl jflsdkjflksjdfl kjsdlfkj lsdkfj lskdfj");
yyjson_mut_obj_add(root, obj, item);
i++;
}
else{
char cnt[5];itoa(d,&cnt,10);
yyjson_mut_obj_remove_str(root,cnt);
yyjson_mut_doc *alc = yyjson_mut_doc_new(NULL);
yyjson_mut_doc_mut_copy(doc,alc);
yyjson_mut_doc_free(doc);
doc = yyjson_mut_doc_new(alc);
root = yyjson_mut_obj(doc);
if(d==0){
i=0;
d=16;
}
d--;
}
}
but this is trash i think :D help!
I'm not sure what you want...
For this loop code, it is more efficient to clean up memory while d==0
. This is a space-time trade off.
I'm not sure what you want... For this loop code, it is more efficient to clean up memory while
d==0
. This is a space-time trade off.
I need to get an object that is always in memory and its structure is available at any time. However, I don't want to leak memory when I delete its elements. You told me that i can use the method to copy the doc and then free it (hovever i don't understand this model). I just tried to reproduce this situation above. https://github.com/ibireme/yyjson/issues/83#issuecomment-1118342721
I'm not sure what you want... For this loop code, it is more efficient to clean up memory while
d==0
. This is a space-time trade off.I need to get an object that is always in memory and its structure is available at any time. However, I don't want to leak memory when I delete its elements. You told me that i can use the method to copy the doc and then free it (hovever i don't understand this model). I just tried to reproduce this situation above. #83 (comment)
yyjson is not designed for that, yyjson focus on speed and does not provide a function to free a single value. If you want to free some of these values, this is the only way (current version):
// deep copy all values referenced from root
yyjson_mut_doc *tmp_doc = yyjson_mut_doc_mut_copy(doc, NULL);
// free all old values
yyjson_mut_doc_free(doc);
// replace old doc
doc = tmp_doc;
@ibireme I dont sure, but i have a PANIC take a look pls
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
yyjson_mut_val *root = yyjson_mut_obj(doc);
yyjson_mut_val *obj0 = yyjson_mut_strcpy(doc, "0");
yyjson_mut_val *item = yyjson_mut_obj(doc);
yyjson_mut_obj_add_str(doc, item, "toy", "some toy");
yyjson_mut_obj_add(root, obj0, item);
yyjson_mut_obj_remove_str(root,"0");
yyjson_mut_doc *tmp_doc = yyjson_mut_doc_mut_copy(doc, NULL);
yyjson_mut_doc_free(doc);
doc = tmp_doc;
yyjson_mut_doc_set_root(doc, root);
char *json = yyjson_mut_write(doc, YYJSON_WRITE_PRETTY, NULL);
printf("%s\n", json);
free(json);
@MadDogMayCry0 The memory of yyjson_mut_val
is held by doc
, if you free the doc
, all the values created from it will be freed too.
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
yyjson_mut_val *root = yyjson_mut_obj(doc);
yyjson_mut_doc_set_root(doc, root); // set the root before copy
yyjson_mut_val *obj0 = yyjson_mut_strcpy(doc, "0");
yyjson_mut_val *item = yyjson_mut_obj(doc);
yyjson_mut_obj_add_str(doc, item, "toy", "some toy");
yyjson_mut_obj_add(root, obj0, item);
yyjson_mut_obj_remove_str(root,"0");
yyjson_mut_doc *tmp_doc = yyjson_mut_doc_mut_copy(doc, NULL);
yyjson_mut_doc_free(doc); // free all values
doc = tmp_doc;
// yyjson_mut_doc_set_root(doc, root); // the `root` is created from old doc, no longer valid here
char *json = yyjson_mut_write(doc, YYJSON_WRITE_PRETTY, NULL);
printf("%s\n", json);
free(json);
@ibireme Hmmm...
void json(){
int i = 0;
int d = 5;
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
yyjson_mut_val *root = yyjson_mut_obj(doc);
yyjson_mut_doc_set_root(doc, root);
while(true){
if(i<=5){
char cnt[5];itoa(i,&cnt,10);
yyjson_mut_val *obj = yyjson_mut_strcpy(doc, cnt);
yyjson_mut_val *item = yyjson_mut_obj(doc);
yyjson_mut_obj_add_str(doc, item, "toy", "some toy");
yyjson_mut_obj_add(root, obj, item);
i++;
}
else{
char cnt[5];itoa(d,&cnt,10);
yyjson_mut_obj_remove_str(root,cnt);
yyjson_mut_doc *tmp_doc = yyjson_mut_doc_mut_copy(doc, NULL);
yyjson_mut_doc_free(doc);
doc = tmp_doc;
d--;
if(d==-1){
i=0;
d=5;
}
}
char *json = yyjson_mut_write(doc, YYJSON_WRITE_PRETTY, NULL);
printf("%s\n", json);
free(json);
}
}
its can only get first DELETION cycle (i>5), then did deleted key "5", and when it trying to delete key "4" then core panic :(
Same mistake:
void json(){
int i = 0;
int d = 5;
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
yyjson_mut_val *root = yyjson_mut_obj(doc);
yyjson_mut_doc_set_root(doc, root);
while(true){
if(i<=5){
char cnt[5];itoa(i,&cnt,10);
yyjson_mut_val *obj = yyjson_mut_strcpy(doc, cnt);
yyjson_mut_val *item = yyjson_mut_obj(doc);
yyjson_mut_obj_add_str(doc, item, "toy", "some toy");
yyjson_mut_obj_add(root, obj, item);
i++;
}
else{
char cnt[5];itoa(d,&cnt,10);
yyjson_mut_obj_remove_str(root,cnt);
yyjson_mut_doc *tmp_doc = yyjson_mut_doc_mut_copy(doc, NULL);
yyjson_mut_doc_free(doc); // `root` is also freed
doc = tmp_doc;
root = yyjson_mut_doc_get_root(doc); // get new `root` from new `doc`
d--;
if(d==-1){
i=0;
d=5;
}
}
char *json = yyjson_mut_write(doc, YYJSON_WRITE_PRETTY, NULL);
printf("%s\n", json);
free(json);
}
}
@ibireme hmm. me again. It's seems to be something strange.
void json(){
int i = 0;
int d = 500;
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
yyjson_mut_val *root = yyjson_mut_obj(doc);
yyjson_mut_doc_set_root(doc, root);
while(true){
if(i<=500){
char cnt[5];itoa(i,&cnt,10);
yyjson_mut_val *obj = yyjson_mut_strcpy(doc, cnt);
yyjson_mut_val *item = yyjson_mut_obj(doc);
yyjson_mut_obj_add_str(doc, item, "toy", "some toy djfhsdjkfh kjsdfhkjsdhfkjhs dkjfhskdj hfkjsdhf kjsdhfk jhsdkjfh skdjhf kjsdhf kjshdkfj hsdkjf hksjdhf ksjfh kjsdhfkjsdhfkjhsdkj hfksjdh fkjsdhf kjshdkfj hskjdfh");
yyjson_mut_obj_add(root, obj, item);
i++;
}
else{
char cnt[5];itoa(d,&cnt,10);
yyjson_mut_obj_remove_str(root,cnt);
yyjson_mut_doc *tmp_doc = yyjson_mut_doc_mut_copy(doc, NULL);
yyjson_mut_doc_free(doc);
doc = tmp_doc;
root = yyjson_mut_doc_get_root(doc);
d--;
if(d==-1){
i=0;
d=500;
}
}
// char *json = yyjson_mut_write(doc, YYJSON_WRITE_PRETTY, NULL);
// printf("%s\n", json);
// free(json);
}
}
if this line is in game
char *json = yyjson_mut_write(doc, YYJSON_WRITE_PRETTY, NULL);
printf("%s\n", json);
free(json);
then its ok, and i see that mut_cpy and fee works and took 1027uS of time. When this block of code above is commented, then after two normal "DELITING" for keys 500 and 499 (took 1000uS of time) then on key 498 and next others its took only 2uS and seems to be DOC is {} becuse i see that RAM will newer changes after that and its full and free.
I tested your code in macOS+clang and checked with address sanitizer/footprint, and it seems to work fine. If your memory is really small, you should check each return value to make sure the memory allocation was successful.
Besides, you should release the memory once inside d==-1
block.
@ibireme
I tested your code in macOS+clang and checked with address sanitizer/footprint, and it seems to work fine. If your memory is really small, you should check each return value to make sure the memory allocation was successful.
The lib is terrable stable and fast! Yes, you are right about memory,- i forgoth, that copy structure needs ram for its self.
Bad for me your very cool library is not suitable for my use case :( I need to free memory every time an element is deleted. Maybe in the future you will add some new type of elements for such scenarios. Thank you for help!
@ibireme Ok, i just use _free when no keys inside of doc and a many keys has been deleted before it. It's helps but i don't sure this is a right way :) I will add examples as i promised later! Thank you :) :+1:
@ibireme This is me again.. I fight for w freedom, and try to change "value"
const char *str = "{\"key\":\"value\"}";
yyjson_doc *json = yyjson_read(str, strlen(str), 0);
yyjson_val *val = yyjson_mut_doc_get_root(json);
yyjson_mut_obj_put(val,"key","hehe");
if(json){
yyjson_val *name = yyjson_obj_get(val, "key");
printf("name: %s\n", yyjson_get_str(name));
}
yyjson_doc_free(json);
but still have "value" :(
const char *str = "{\"key\":\"value\"}"; yyjson_doc *json = yyjson_read(str, strlen(str), 0); // Incompatible pointer types initializing 'yyjson_val *' (aka 'struct yyjson_val *') with an expression of type 'yyjson_mut_val *' (aka 'struct yyjson_mut_val *') yyjson_val *val = yyjson_mut_doc_get_root(json); // Incompatible pointer types passing 'char [4]' to parameter of type 'yyjson_mut_val *' (aka 'struct yyjson_mut_val *') // Incompatible pointer types passing 'char [5]' to parameter of type 'yyjson_mut_val *' (aka 'struct yyjson_mut_val *') // Incompatible pointer types passing 'yyjson_val *' (aka 'struct yyjson_val *') to parameter of type 'yyjson_mut_val *' (aka 'struct yyjson_mut_val *') yyjson_mut_obj_put(val,"key","hehe"); if(json){ yyjson_val *name = yyjson_obj_get(val, "key"); printf("name: %s\n", yyjson_get_str(name)); } yyjson_doc_free(json);
You should read the documentation, or at least use an editor/IDE with error checking.
@ibireme
UPD Ok, i got it....
const char *str = "{\"key\":\"value\"}";
yyjson_doc *input = yyjson_read(str, strlen(str), 0);
yyjson_mut_doc *json = yyjson_doc_mut_copy(input, NULL);
i hope this is a right way.
const char *str = "{\"key\":\"value\"}";
yyjson_mut_doc *json = yyjson_read(str, strlen(str), 0);
yyjson_mut_val *base = yyjson_mut_doc_get_root(json);
if(json){
yyjson_mut_val *name = yyjson_mut_obj_get(base, "key");
printf("name: %s\n", yyjson_mut_get_str(name));
}
yyjson_mut_doc_free(json);
warning: initialization of
'yyjson_mut_doc *' {aka 'struct yyjson_mut_doc *'} from incompatible pointer type 'yyjson_doc *' {aka 'struct yyjson_doc *'} [-Wincompatible-pointer-types]
yyjson_mut_doc *json = yyjson_read(str, strlen(str), 0);
@ibireme I really don't understand on how to read this documentation and understand it :(
/** Replaces value from the object with given key.
@warning This function takes a linear search time. */
yyjson_api_inline bool yyjson_mut_obj_replace(yyjson_mut_val *obj,
yyjson_mut_val *key,
yyjson_mut_val *val);
Ok, nice! Let's go!
const char *str = "{\"key\":\"value\"}";
yyjson_doc *input = yyjson_read(str, strlen(str), 0);
yyjson_mut_doc *json = yyjson_doc_mut_copy(input, NULL);
yyjson_mut_val *base = yyjson_mut_doc_get_root(json);
yyjson_mut_val *key = yyjson_mut_obj_get(base, "key");
yyjson_mut_val *val = yyjson_mut_str(json,"blabla");
yyjson_mut_obj_replace(base,key,val);
if(json){
yyjson_mut_val *name = yyjson_mut_obj_get(base, "key");
printf("name: %s\n", yyjson_mut_get_str(name));
}
yyjson_mut_doc_free(json);
output:
"value"
...
const char *str = "{\"key\":\"value\"}";
yyjson_doc *input = yyjson_read(str, strlen(str), 0);
yyjson_mut_doc *json = yyjson_doc_mut_copy(input, NULL);
yyjson_mut_val *base = yyjson_mut_doc_get_root(json);
yyjson_mut_val *key = yyjson_mut_str(json, "key");
yyjson_mut_val *val = yyjson_mut_str(json, "dolphin");
yyjson_mut_obj_put(base,key,val);
if(json){
yyjson_mut_val *name = yyjson_mut_obj_get(base, "key");
printf("name: %s\n", yyjson_mut_get_str(name));
}
yyjson_mut_doc_free(json);
output: "dolphin" ...
Here is a mistake:
const char *str = "{\"key\":\"value\"}"; yyjson_doc *input = yyjson_read(str, strlen(str), 0); yyjson_mut_doc *json = yyjson_doc_mut_copy(input, NULL); yyjson_mut_val *base = yyjson_mut_doc_get_root(json); yyjson_mut_val *key = yyjson_mut_obj_get(base, "key"); // this returns "value", not "key" yyjson_mut_val *val = yyjson_mut_str(json,"blabla"); yyjson_mut_obj_replace(base,key,val); // and this will fail, nothing will be changed if(json){ yyjson_mut_val *name = yyjson_mut_obj_get(base, "key"); printf("name: %s\n", yyjson_mut_get_str(name)); } yyjson_mut_doc_free(json);
output:
"value"
This code looks correct:
const char *str = "{\"key\":\"value\"}"; yyjson_doc *input = yyjson_read(str, strlen(str), 0); yyjson_mut_doc *json = yyjson_doc_mut_copy(input, NULL); yyjson_mut_val *base = yyjson_mut_doc_get_root(json); yyjson_mut_val *key = yyjson_mut_str(json, "key"); yyjson_mut_val *val = yyjson_mut_str(json, "dolphin"); yyjson_mut_obj_put(base,key,val); if(json){ yyjson_mut_val *name = yyjson_mut_obj_get(base, "key"); printf("name: %s\n", yyjson_mut_get_str(name)); } yyjson_mut_doc_free(json);
output: "dolphin" ...
This library is optimized for building JSON, not manipulating JSON objects frequently. The key-value pairs of objects are stored in linked list, so adding is fast, but searching and replacing is slow.
@ibireme
yyjson_mut_val *key = yyjson_mut_obj_get(base, "key"); // this returns "value", not "key"
how to get key? :)
@ibireme
yyjson_mut_val *key = yyjson_mut_obj_get(base, "key"); // this returns "value", not "key"
how to get key? :)
As your second code snippet above, use yyjson_mut_str()
to create the key, or use iterator/for_each macro
to iterate over all keys.
@ibireme Me again.. I don;t realy sure about BUG, but take a look
bool json_put(yyjson_mut_doc *json,yyjson_mut_val* obj,char* obj_key, char* obj_val){
yyjson_mut_val *key = yyjson_mut_str(json, obj_key);
yyjson_mut_val *val = yyjson_mut_str(json, obj_val);
// I tryed mut_put with same result
return yyjson_mut_obj_replace(obj,key,val);
}
char buff[256]="{\"dhcp\":\"false\",\"ip\":\"192.168.1.15\",\"mask\":\"255.255.255.0\",\"gw\":\"192.168.1.1\",\"dns1\":\"192.168.1.1\",\"dns2\":\"8.8.8.8\"}";
yyjson_mut_doc *eth_json = json_doc(buff,strlen(buff));
yyjson_mut_val *eth_root = yyjson_mut_doc_get_root(eth_json);
Now, if i use
json_put(eth_json,eth_root,"dhcp","true");
i got
{"dhcp":"true","ip":"192.168.1.15","mask":"255.255.255.0","gw":"192.168.1.1","dns1":"192.168.1.1","dns2":"8.8.8.8"}
and after "false" seems to be ok. When i then try to change another elements
json_put(eth_json,eth_root,"ip","192.168.1.7");
json_put(eth_json,eth_root,"gw","192.168.1.1");
json_put(eth_json,eth_root,"mask","255.255.255.0");
json_put(eth_json,eth_root,"dns1","192.168.1.1");
json_put(eth_json,eth_root,"dns2","8.8.8.7");
I got after
{"dhcp":"68.1.7","ip":"192.168.1.7","mask":"255.255.255.0","gw":"192.168.1.1","dns1":"192.168.1.1","dns2":"8.8.8.7"}
amd when now i repeat this one again
json_put(eth_json,eth_root,"dhcp","true");
i got
{"dhcp":"true","ip":"dhcp\u0000true\u0000\u0000","mask":"255.255.255.0","gw":"192.168.1.1","dns1":"192.168.1.1","dns2":"8.8.8.7"}
Hmm...
I have tested with these codes and it seems OK:
char buff[256]="{\"dhcp\":\"false\",\"ip\":\"192.168.1.15\",\"mask\":\"255.255.255.0\",\"gw\":\"192.168.1.1\",\"dns1\":\"192.168.1.1\",\"dns2\":\"8.8.8.8\"}";
yyjson_doc *doc = yyjson_read(buff, strlen(buff), 0);
yyjson_mut_doc *eth_json = yyjson_doc_mut_copy(doc, NULL);
yyjson_mut_val *eth_root = yyjson_mut_doc_get_root(eth_json);
json_put(eth_json,eth_root,"dhcp","true");
json_put(eth_json,eth_root,"ip","192.168.1.7");
json_put(eth_json,eth_root,"gw","192.168.1.1");
json_put(eth_json,eth_root,"mask","255.255.255.0");
json_put(eth_json,eth_root,"dns1","192.168.1.1");
json_put(eth_json,eth_root,"dns2","8.8.8.7");
json_put(eth_json,eth_root,"dhcp","true");
char *str = yyjson_mut_write(eth_json, 0, NULL);
output:
"{\"dhcp\":\"true\",\"ip\":\"192.168.1.7\",\"mask\":\"255.255.255.0\",\"gw\":\"192.168.1.1\",\"dns1\":\"192.168.1.1\",\"dns2\":\"8.8.8.7\"}"
I noticed that the value of ip
contains some NUL
characters, maybe you are not using a constant string. Try using the yyjson_mut_strcpy() function to copy the string into val
. See comment: https://github.com/ibireme/yyjson/blob/331037f038c2e673f6567b132aede74196f87b58/src/yyjson.h#L1676-L1679
@ibireme
I have tested with these codes and it seems OK:
char buff[256]="{\"dhcp\":\"false\",\"ip\":\"192.168.1.15\",\"mask\":\"255.255.255.0\",\"gw\":\"192.168.1.1\",\"dns1\":\"192.168.1.1\",\"dns2\":\"8.8.8.8\"}"; yyjson_doc *doc = yyjson_read(buff, strlen(buff), 0); yyjson_mut_doc *eth_json = yyjson_doc_mut_copy(doc, NULL); yyjson_mut_val *eth_root = yyjson_mut_doc_get_root(eth_json); json_put(eth_json,eth_root,"dhcp","true"); json_put(eth_json,eth_root,"ip","192.168.1.7"); json_put(eth_json,eth_root,"gw","192.168.1.1"); json_put(eth_json,eth_root,"mask","255.255.255.0"); json_put(eth_json,eth_root,"dns1","192.168.1.1"); json_put(eth_json,eth_root,"dns2","8.8.8.7"); json_put(eth_json,eth_root,"dhcp","true"); char *str = yyjson_mut_write(eth_json, 0, NULL);
output:
"{\"dhcp\":\"true\",\"ip\":\"192.168.1.7\",\"mask\":\"255.255.255.0\",\"gw\":\"192.168.1.1\",\"dns1\":\"192.168.1.1\",\"dns2\":\"8.8.8.7\"}"
I noticed that the value of
ip
contains someNUL
characters, maybe you are not using a constant string. Try using the yyjson_mut_strcpy() function to copy the string intoval
. See comment:
When i did it in line like you, it's works too/ But i'm sure, if you try to separate it in a time, it's will works like described above. Try to write console scenario, and when you send "1" to console, PUT "dhcp", and when u press "2" put IP. after 3'st try u become this BUG. But don't FREE json after each PUT's.
@MadDogMayCry0
When you use console input, your string is not constant
and the memory it points to may be modified. So you should use yyjson_mut_strcpy() to copy that string.
and add to it
to become
Great lib with bad doc =(