Closed sudharkrish closed 5 years ago
size
is 1 then the next token is a value, otherwise if it's 0 then next token will be another key. It's good to remember that to avoid errors like pointed out in #125 Thanks for checking. I tried few options, but ran into issues.
I made changes to simple.c example program in your repo.
Here below is the JSON_STRING updatedwith a group with key, value pair:
static const char *JSON_STRING = "{\"user\": \"johndoe\", \"admin\": false, \"uid\": 1000,\n " "\"groups\": [\"users\", \"wheel\", \"audio\", \"video\"],\n " "\"plat_conf\": {\"ip_addr\": \"127.0.0.1\",\"port_num\": \"4444\"}}"; And this the section I added to parse the group with key, value pairs:
else if (jsoneq(JSON_STRING, &t[i], "plat_conf") == 0) { int j; printf("- Groups:\n"); if (t[i+1].type != JSMN_OBJECT) { continue; / We expect groups to be an array of strings / } for (j = 0; j < t[i+1].size; j++) { jsmntok_t g = &t[i+j+2]; printf(" %.*s\n", g->end - g->start, JSON_STRING + g->start); } i += t[i+1].size + 1; }
Here is my output:
As you can see above the parsing fails. Can you give some code snippets on what changes are needed to parse the key, value pair, in the example above.
Here is the complete simple.c, with my changes:
/*
static const char *JSON_STRING = "{\"user\": \"johndoe\", \"admin\": false, \"uid\": 1000,\n " "\"groups\": [\"users\", \"wheel\", \"audio\", \"video\"],\n " "\"plat_conf\": {\"ip_addr\": \"127.0.0.1\",\"port_num\": \"4444\"}}";
static int jsoneq(const char json, jsmntok_t tok, const char *s) { if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start && strncmp(json + tok->start, s, tok->end - tok->start) == 0) { return 0; } return -1; }
int main() { int i; int r; jsmn_parser p; jsmntok_t t[128]; / We expect no more than 128 tokens /
jsmn_init(&p);
r = jsmn_parse(&p, JSON_STRING, strlen(JSON_STRING), t, sizeof(t)/sizeof(t[0]));
if (r < 0) {
printf("Failed to parse JSON: %d\n", r);
return 1;
}
/* Assume the top-level element is an object */
if (r < 1 || t[0].type != JSMN_OBJECT) {
printf("Object expected\n");
return 1;
}
/* Loop over all keys of the root object */
for (i = 1; i < r; i++) {
if (jsoneq(JSON_STRING, &t[i], "user") == 0) {
/* We may use strndup() to fetch string value */
printf("- User: %.*s\n", t[i+1].end-t[i+1].start,
JSON_STRING + t[i+1].start);
i++;
} else if (jsoneq(JSON_STRING, &t[i], "admin") == 0) {
/* We may additionally check if the value is either "true" or "false" */
printf("- Admin: %.*s\n", t[i+1].end-t[i+1].start,
JSON_STRING + t[i+1].start);
i++;
} else if (jsoneq(JSON_STRING, &t[i], "uid") == 0) {
/* We may want to do strtol() here to get numeric value */
printf("- UID: %.*s\n", t[i+1].end-t[i+1].start,
JSON_STRING + t[i+1].start);
i++;
} else if (jsoneq(JSON_STRING, &t[i], "groups") == 0) {
int j;
printf("- Groups:\n");
if (t[i+1].type != JSMN_ARRAY) {
continue; /* We expect groups to be an array of strings */
}
for (j = 0; j < t[i+1].size; j++) {
jsmntok_t *g = &t[i+j+2];
printf(" * %.*s\n", g->end - g->start, JSON_STRING + g->start);
}
i += t[i+1].size + 1;
} else if (jsoneq(JSON_STRING, &t[i], "plat_conf") == 0) {
int j;
printf("- Groups:\n");
if (t[i+1].type != JSMN_OBJECT) {
continue; /* We expect groups to be an array of strings */
}
for (j = 0; j < t[i+1].size; j++) {
jsmntok_t *g = &t[i+j+2];
printf(" * %.*s\n", g->end - g->start, JSON_STRING + g->start);
}
i += t[i+1].size + 1;
} else {
printf("Unexpected key: %.*s\n", t[i].end-t[i].start,
JSON_STRING + t[i].start);
}
}
return EXIT_SUCCESS;
}
It will be great, if you can provide some code snippets, on what changes are needed to parse group with key, value pair in the modified simple.c that I had pasted previously.
You're on the right track. In the for loop you added you now have to, for each token, see if it's size
attribute is equal 1. Then the next token is a value.
for (j = 0; j < t[i+1].size; j++) {
jsmntok_t *g = &t[i+j+2];
printf(" * %.*s\n", g->end - g->start, JSON_STRING + g->start);
if(g->size == 1) { //key has a value
j++; //jump to next token
g = &t[i+j+2]; //you know the drill
printf(" * %.*s\n", g->end - g->start, JSON_STRING + g->start);
}
}
Thanks for your inputs.
I tried your suggestion, but ran into issue. For example, since I have 2 rows for key-value pair, under the group plat_info, I was expecting, t[1+1].size will be 2. But I am getting 0 for t[1+1].size, so its NOT looping all the entries. And same thing even with the group array, which is existing code in the repo.
Ideally, I would like to compare the key field, and then print the value. For example, jsoneq(... "ip_addr") then print the value field.
Can you provide some example code that can do above.
Here is my modified simple.c, along with the output:
/*
static const char *JSON_STRING = "{\"user\": \"johndoe\", \"admin\": false, \"uid\": 1000,\n " "\"groups\": [\"users\", \"wheel\", \"audio\", \"video\"],\n " "\"plat_conf\": {\"ip_addr\": \"127.0.0.1\",\"port_num\": \"4444\"}}";
static int jsoneq(const char json, jsmntok_t tok, const char *s) { if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start && strncmp(json + tok->start, s, tok->end - tok->start) == 0) { return 0; } return -1; }
int main() { int i; int r; jsmn_parser p; jsmntok_t t[128]; / We expect no more than 128 tokens /
jsmn_init(&p);
r = jsmn_parse(&p, JSON_STRING, strlen(JSON_STRING), t, sizeof(t)/sizeof(t[0]));
if (r < 0) {
printf("Failed to parse JSON: %d\n", r);
return 1;
}
/* Assume the top-level element is an object */
if (r < 1 || t[0].type != JSMN_OBJECT) {
printf("Object expected\n");
return 1;
}
/* Loop over all keys of the root object */
for (i = 1; i < r; i++) {
if (jsoneq(JSON_STRING, &t[i], "user") == 0) {
/* We may use strndup() to fetch string value */
printf("- User: %.*s\n", t[i+1].end-t[i+1].start,
JSON_STRING + t[i+1].start);
i++;
} else if (jsoneq(JSON_STRING, &t[i], "admin") == 0) {
/* We may additionally check if the value is either "true" or "false" */
printf("- Admin: %.*s\n", t[i+1].end-t[i+1].start,
JSON_STRING + t[i+1].start);
i++;
} else if (jsoneq(JSON_STRING, &t[i], "uid") == 0) {
/* We may want to do strtol() here to get numeric value */
printf("- UID: %.*s\n", t[i+1].end-t[i+1].start,
JSON_STRING + t[i+1].start);
i++;
} else if (jsoneq(JSON_STRING, &t[i], "groups") == 0) {
int j;
printf("- Groups:\n");
if (t[i+1].type != JSMN_ARRAY) {
continue; /* We expect groups to be an array of strings */
}
printf("ARRAY group size=>t[i+1].size = %d\n", t[1+1].size);
for (j = 0; j < t[i+1].size; j++) {
jsmntok_t *g = &t[i+j+2];
printf(" * %.*s\n", g->end - g->start, JSON_STRING + g->start);
}
i += t[i+1].size + 1;
} else if (jsoneq(JSON_STRING, &t[i], "plat_conf") == 0) {
int j;
printf("- Groups:\n");
if (t[i+1].type != JSMN_OBJECT) {
continue; // We expect groups to be an array of strings
}
printf("KEY-VALUE group size=>t[i+1].size = %d\n", t[1+1].size);
for (j = 0; j < t[i+1].size; j++) {
jsmntok_t *g = &t[i+j+2];
//printf(" * %.*s\n", g->end - g->start, JSON_STRING + g->start);
if(g->size == 1) { //key has a value
j++; //jump to next token
g = &t[i+j+2]; //you know the drill
printf(" * %.*s\n", g->end - g->start, JSON_STRING + g->start);
}
}
//i += t[i+1].size + 1;
i++;
j = 1;
//for (j = 0; j < t[i+1].size; j++) {
jsmntok_t *g = &t[i+j+2];
//printf(" * %.*s\n", g->end - g->start, JSON_STRING + g->start);
if(g->size == 1) { //key has a value
j++; //jump to next token
g = &t[i+j+2]; //you know the drill
printf(" * %.*s\n", g->end - g->start, JSON_STRING + g->start);
}
//}
i += t[i+1].size + 1;
i += j + 1;
}
else {
printf("Unexpected key: %.*s\n", t[i].end-t[i].start,
JSON_STRING + t[i].start);
}
}
return EXIT_SUCCESS;
}
OUTPUT:
it's supposed to be i+1
not 1+1
when you print the size.
Can you let me know, if a group with key, value pair is supported.
For example, if I have a json file, that is read by my program, and lets say the contents of the json file is below: { "plat_conf": { "ip_addr": "127.0.0.1", "port_num": "4444" }
}
The program simple.c, under example directory, has an example of a group that has an array of strings.
I tried to modify simple.c, to parse a group with key, value pair, and ran into issues.
Can you please let me know below: