MXS-1220: Add JSON Pointer support for json_t objects

Using the JSON Pointer syntax specified in RFC 6901
(https://tools.ietf.org/html/rfc6901) allows for a convenient way to
access values deep in a JSON object.
This commit is contained in:
Markus Mäkelä
2017-05-04 11:00:25 +03:00
parent 432a6d6f28
commit 2f8db4ec1a
4 changed files with 379 additions and 0 deletions

View File

@ -61,3 +61,73 @@ void mxs_json_add_relation(json_t* rel, const char* id, const char* type)
json_object_set_new(obj, CN_TYPE, json_string(type));
json_array_append(data, obj);
}
static string grab_next_component(string* s)
{
std::string& str = *s;
while (str.length() > 0 && str[0] == '/')
{
str.erase(str.begin());
}
size_t pos = str.find("/");
string rval;
if (pos != string::npos)
{
rval = str.substr(0, pos);
str.erase(0, pos);
return rval;
}
else
{
rval = str;
str.erase(0);
}
return rval;
}
static bool is_integer(const string& str)
{
char* end;
return strtol(str.c_str(), &end, 10) >= 0 && *end == '\0';
}
static json_t* mxs_json_pointer_internal(json_t* json, string str)
{
json_t* rval = NULL;
string comp = grab_next_component(&str);
if (comp.length() == 0)
{
return json;
}
if (json_is_array(json) && is_integer(comp))
{
size_t idx = strtol(comp.c_str(), NULL, 10);
if (idx < json_array_size(json))
{
rval = mxs_json_pointer_internal(json_array_get(json, idx), str);
}
}
else if (json_is_object(json))
{
json_t* obj = json_object_get(json, comp.c_str());
if (obj)
{
rval = mxs_json_pointer_internal(obj, str);
}
}
return rval;
}
json_t* mxs_json_pointer(json_t* json, const char* json_ptr)
{
return mxs_json_pointer_internal(json, json_ptr);
}