0

I have the following JSON object, from which I need to retrieve values of certain keys. For example, in outer JSON object, I need only "timestamp" and "type", next from a nested "meta" object I need only "version", and from nested "payload" I want fields "reason", "type" and "condition" from its nested object "data"

   {
      "timestamp": "1568961295627",
      "type": "test",
      "namespace": "internal",
      "meta": {
        "version": "2.0-test",
        "id": "123"
      },
      "payload": {
        "data": {
        "reason": "user_request",
        "type": "asd",
        "condition": "bad"
        },
        "contentType": "application/json"
      }
    }

I wrote a function to retrieve such data:

void log_values(json_t *data) {
    json_t *obj = NULL;
    json_t *nested = NULL;
    syslog(LOG_INFO, "%s: ", json_string_value(json_object_get(data, "timestamp")));
    syslog(LOG_INFO, "%s: ", json_string_value(json_object_get(data, "type")));
    obj = json_object_get(data, "meta");
    syslog(LOG_INFO, "%s: ", json_string_value(json_object_get(obj, "version")));
    obj = json_object_get(data, "payload");
    nested = json_object_get(obj, "data");
    syslog(LOG_INFO, "%s: ", json_string_value(json_object_get(nested, "reson")));
    syslog(LOG_INFO, "%s: ", json_string_value(json_object_get(nested, "type")));
    syslog(LOG_INFO, "%s: ", json_string_value(json_object_get(nested, "condition")));
}

However, the code looks repetitive and I'm wondering if there is any way to generalize it? The first thing which came to mind is to create a jagged array of pointers to keys needed for each stage, and then walk through the array and retrieve only certain keys on certain nesting level, for example:

char *nested0 = {"timestamp", "type"};
char *nested1 = {"anomaly", "version"};
char *nested2 = {"reason", "type", "condition"};
char *(*keys[])[] = { &nested0, &nested1, &nested2 }

But, this solution does not solve problem regarding where to store key names, which point to nested JSONs (e.g "meta, payload, data").

So, the question is: How to generalize the aforementioned code and what data structure should I use to store names of keys holding a json object and keys for which I need to get values.

yy7k
  • 61
  • 3

1 Answers1

0

Take a look at jsmn, it should fit your needs : https://github.com/zserge/jsmn

exemple of what you could do with jsmn :

[user@machine ~]$ ./json_parser_with_keys test.json timestamp type meta/version
timestamp=1568961295627
type=test
meta/version=2.0-test
[user@machine ~]$ ./json_parser_full test.json
/timestamp=1568961295627
/type=test
/namespace=internal
/meta/version=2.0-test
/meta/id=123
/payload/data/reason=user_request
/payload/data/type=asd
/payload/data/condition=bad
/payload/contentType=application/json
[user@machine ~]$
Julien
  • 508
  • 2
  • 6
  • 13
  • Could you add what it does to make extracting the fields easier and how it can be used to achieve it? – Gerhardh Sep 17 '20 at 08:39
  • the parse fonction of jsmn returns an array of a structure containing pointer to the start and end to the differents object (=> called tokens in jsmn) in your json. You just need to write a program to go through this array of tokens, and do whatever you need to do with them. I edited the answer to add an example of what does my implementation on your json. – Julien Sep 17 '20 at 09:26
  • full code here : https://github.com/juliengrandjean/jsmn_perso – Julien Sep 17 '20 at 09:35