sheredom / json.h

🗄️ single header json parser for C and C++
The Unlicense
698 stars 77 forks source link

[Feature Request] Lookup value via given key #79

Open ddengster opened 2 years ago

ddengster commented 2 years ago

Great work so far.

However one thing that would help tremendously is to have a (family of) utility function to look up values by a given key - right now I'd have to iterate through a linked list of the members of the json object, which makes the implemenation curve annoying. This has it's own performance implications ofc.

Parson has something like these:

JSON_Value* json_object_get_value(const JSON_Object* object, const char* name);
const char* json_object_get_string(const JSON_Object* object, const char* name);
JSON_Array* json_object_get_array(const JSON_Object* object, const char* name);
double        json_object_get_number(const JSON_Object* object, const char* name);
sheredom commented 2 years ago

These would just be wrappers around me also traversing the linked list to find the key that matches. If you went for multiple keys it'd be very inefficient to do it this way.

Happy to accept a PR to add these helper functions if you think it is worth it though, we'll just have to document the worst case behaviour.

duarm commented 2 years ago

I use this, the api is a bit different tho.

struct json_value_s *root = json_parse(data, size);

struct json_object_element_s * const start = ((struct json_object_s *)root->payload)->start;
struct json_object_element_s *curr = start;

double width = 0;
if (json_object_get_double("width", start, &curr, &width) == 0) {
    printf("width: %.1f\n", width);
}
curr = curr->next;

int size = 0;
if (json_object_get_int("size", start, &curr, &size) == 0) {
    printf("size: %d\n", size);
}
curr = curr->next;

struct json_array_s *data;
if (json_object_get_array("data", start, &curr, &data) == 0) {
    struct json_array_element_s *json_value = data->start;
    for (size_t i = 0; i < layer_data->length; i++) {
        printf("%d\n", atoi(json_value_as_number(json_value->value)->number));
        json_value = json_value->next;
    }
}
curr = curr->next;
...

it traverses the list starting from curr until it finds the key, looping around to start if necessary, the converted value is set to the last parameter, and curr is set to the element of the key found or the same curr if not found. If you continue passing curr->next to the next call, It becomes a linear search, if you're reading the json in order, it's still an O(n).

it works great for me, if someone can point out a more convenient api, i would be glad to help, searching a json by key is a common operation, and worth the inclusion.