libmaxminddb
libmaxminddb copied to clipboard
Iterating over map or array returned with MMDB_get_value()
I am working with the example data from the library's documentation:
{
"names": {
"en": "Germany",
"de": "Deutschland"
},
"cities": [ "Berlin", "Frankfurt" ]
}
Say I call
MMDB_get_value(&result.entry, &entry_data, "names", NULL);
This will produce entry_data.type == 7
, which is a MAP, as expected. How can I then retrieve the values for specific keys in this map? Because entry_data
is a MMDB_entry_data_s
and NOT a MMDB_entry_s
, I cannot pass it into MMDB_get_value
.
Same question would apply for an array:
MMDB_get_value(&result.entry, &entry_data, "cities", NULL);
This will produce with entry_data.type == 11
, which is an ARRAY, as expected. How can I then retrieve the values for specific positions in this array?
To iterate over collection, you will need to use the offset_to_next
field.
See this example for maps:
https://github.com/maxmind/libmaxminddb/blob/ed7a4252c8a2f19885479fe35ea9e8a12106a1ec/src/maxminddb.c#L1255-L1283
And for arrays:
https://github.com/maxmind/libmaxminddb/blob/ed7a4252c8a2f19885479fe35ea9e8a12106a1ec/src/maxminddb.c#L1231-L1239
Thanks for the quick reply @oschwald. Is there a way to directly retrieve, without iteration, the value for a given key in a map, or the value for a given position in an array?
Also, there seems to be no public API to do any of this; the code you pointed to depends on a couple of macros and static functions, which I would have to replicate in my code. Is this correct? If so, are there any plans to expose such APIs as part of the stable public interface of the library? I would love to have the equivalent of at least map_retrieve(key)
, map_get_keys()
, array_get_size()
, array_fetch(position)
.
You can look up particular map values or array index values directly with MMDB_get_values()
, e.g., from your example above:
MMDB_get_value(&result.entry, &entry_data, "names", "en", NULL);
This would look up the value for the en
key of the names
map.
Similarly, the following would look up the first city:
MMDB_get_value(&result.entry, &entry_data, "cities", "0", NULL);
Yes, this is how I am doing it today. But if I know before hand I will access several keys inside a map, I think it would be more efficient to first get the map entry, and then get the value for each key, instead of repeatedly searching for "names" / "en", "names" / "es", "names" / "de", etc.
I see. I don't think we expose any functions to do this directly, although you likely could just create a new MMDB_entry_s
with the offset to the map and then use MMDB_get_value
on that.
Ok, thanks for all the hints. I still think it would be nice to have an official API for this kind of access, but I understand if this is out of the scope for the library -- feel free to close the issue if this is not in the plans.