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:
parent
432a6d6f28
commit
2f8db4ec1a
@ -61,4 +61,13 @@ json_t* mxs_json_relationship(const char* host, const char* endpoint);
|
||||
*/
|
||||
void mxs_json_add_relation(json_t* rel, const char* id, const char* type);
|
||||
|
||||
/**
|
||||
* @brief Return value at provided JSON Pointer
|
||||
*
|
||||
* @param json JSON object
|
||||
* @param json_ptr JSON Pointer to object
|
||||
* @return Pointed value or NULL if no value is found
|
||||
*/
|
||||
json_t* mxs_json_pointer(json_t* json, const char* json_ptr);
|
||||
|
||||
MXS_END_DECLS
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ add_executable(testmaxscalepcre2 testmaxscalepcre2.cc)
|
||||
add_executable(testmodulecmd testmodulecmd.cc)
|
||||
add_executable(testconfig testconfig.cc)
|
||||
add_executable(trxboundaryparser_profile trxboundaryparser_profile.cc)
|
||||
add_executable(testjson testjson.cc)
|
||||
target_link_libraries(test_atomic maxscale-common)
|
||||
target_link_libraries(test_adminusers maxscale-common)
|
||||
target_link_libraries(test_buffer maxscale-common)
|
||||
@ -48,6 +49,7 @@ target_link_libraries(testmaxscalepcre2 maxscale-common)
|
||||
target_link_libraries(testmodulecmd maxscale-common)
|
||||
target_link_libraries(testconfig maxscale-common)
|
||||
target_link_libraries(trxboundaryparser_profile maxscale-common)
|
||||
target_link_libraries(testjson maxscale-common)
|
||||
add_test(TestAtomic test_atomic)
|
||||
add_test(TestAdminUsers test_adminusers)
|
||||
add_test(TestBuffer test_buffer)
|
||||
@ -79,6 +81,7 @@ add_test(TestTrxCompare_Select test_trxcompare ${CMAKE_CURRENT_SOURCE_DIR}/../..
|
||||
add_test(TestTrxCompare_Set test_trxcompare ${CMAKE_CURRENT_SOURCE_DIR}/../../../query_classifier/test/set.test)
|
||||
add_test(TestTrxCompare_Update test_trxcompare ${CMAKE_CURRENT_SOURCE_DIR}/../../../query_classifier/test/update.test)
|
||||
add_test(TestTrxCompare_MaxScale test_trxcompare ${CMAKE_CURRENT_SOURCE_DIR}/../../../query_classifier/test/maxscale.test)
|
||||
add_test(TestJson testjson)
|
||||
|
||||
# This test requires external dependencies and thus cannot be run
|
||||
# as a part of the core test set
|
||||
|
297
server/core/test/testjson.cc
Normal file
297
server/core/test/testjson.cc
Normal file
@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
||||
*
|
||||
* Change Date: 2019-07-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include <maxscale/cppdefs.hh>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <maxscale/debug.h>
|
||||
#include <maxscale/jansson.hh>
|
||||
#include <maxscale/json_api.h>
|
||||
|
||||
using std::string;
|
||||
|
||||
const char* test1_json =
|
||||
"{"
|
||||
" \"links\": {"
|
||||
" \"self\": \"http://localhost:8989/v1/servers/\""
|
||||
" },"
|
||||
" \"data\": ["
|
||||
" {"
|
||||
" \"id\": \"server1\","
|
||||
" \"type\": \"servers\","
|
||||
" \"relationships\": {"
|
||||
" \"services\": {"
|
||||
" \"links\": {"
|
||||
" \"self\": \"http://localhost:8989/v1/services/\""
|
||||
" },"
|
||||
" \"data\": ["
|
||||
" {"
|
||||
" \"id\": \"RW-Split-Router\","
|
||||
" \"type\": \"services\""
|
||||
" },"
|
||||
" {"
|
||||
" \"id\": \"SchemaRouter-Router\","
|
||||
" \"type\": \"services\""
|
||||
" },"
|
||||
" {"
|
||||
" \"id\": \"RW-Split-Hint-Router\","
|
||||
" \"type\": \"services\""
|
||||
" },"
|
||||
" {"
|
||||
" \"id\": \"Read-Connection-Router\","
|
||||
" \"type\": \"services\""
|
||||
" }"
|
||||
" ]"
|
||||
" },"
|
||||
" \"monitors\": {"
|
||||
" \"links\": {"
|
||||
" \"self\": \"http://localhost:8989/v1/monitors/\""
|
||||
" },"
|
||||
" \"data\": ["
|
||||
" {"
|
||||
" \"id\": \"MySQL-Monitor\","
|
||||
" \"type\": \"monitors\""
|
||||
" }"
|
||||
" ]"
|
||||
" }"
|
||||
" },"
|
||||
" \"attributes\": {"
|
||||
" \"parameters\": {"
|
||||
" \"address\": \"127.0.0.1\","
|
||||
" \"port\": 3000,"
|
||||
" \"protocol\": \"MySQLBackend\""
|
||||
" },"
|
||||
" \"status\": \"Master, Running\","
|
||||
" \"version_string\": \"10.1.19-MariaDB-1~jessie\","
|
||||
" \"node_id\": 3000,"
|
||||
" \"master_id\": -1,"
|
||||
" \"replication_depth\": 0,"
|
||||
" \"slaves\": ["
|
||||
" 3001,"
|
||||
" 3002,"
|
||||
" 3003"
|
||||
" ],"
|
||||
" \"statictics\": {"
|
||||
" \"connections\": 0,"
|
||||
" \"total_connections\": 0,"
|
||||
" \"active_operations\": 0"
|
||||
" }"
|
||||
" }"
|
||||
" },"
|
||||
" {"
|
||||
" \"id\": \"server2\","
|
||||
" \"type\": \"servers\","
|
||||
" \"relationships\": {"
|
||||
" \"services\": {"
|
||||
" \"links\": {"
|
||||
" \"self\": \"http://localhost:8989/v1/services/\""
|
||||
" },"
|
||||
" \"data\": ["
|
||||
" {"
|
||||
" \"id\": \"RW-Split-Router\","
|
||||
" \"type\": \"services\""
|
||||
" },"
|
||||
" {"
|
||||
" \"id\": \"SchemaRouter-Router\","
|
||||
" \"type\": \"services\""
|
||||
" },"
|
||||
" {"
|
||||
" \"id\": \"RW-Split-Hint-Router\","
|
||||
" \"type\": \"services\""
|
||||
" }"
|
||||
" ]"
|
||||
" },"
|
||||
" \"monitors\": {"
|
||||
" \"links\": {"
|
||||
" \"self\": \"http://localhost:8989/v1/monitors/\""
|
||||
" },"
|
||||
" \"data\": ["
|
||||
" {"
|
||||
" \"id\": \"MySQL-Monitor\","
|
||||
" \"type\": \"monitors\""
|
||||
" }"
|
||||
" ]"
|
||||
" }"
|
||||
" },"
|
||||
" \"attributes\": {"
|
||||
" \"parameters\": {"
|
||||
" \"address\": \"127.0.0.1\","
|
||||
" \"port\": 3001,"
|
||||
" \"protocol\": \"MySQLBackend\""
|
||||
" },"
|
||||
" \"status\": \"Slave, Running\","
|
||||
" \"version_string\": \"10.1.19-MariaDB-1~jessie\","
|
||||
" \"node_id\": 3001,"
|
||||
" \"master_id\": 3000,"
|
||||
" \"replication_depth\": 1,"
|
||||
" \"slaves\": [],"
|
||||
" \"statictics\": {"
|
||||
" \"connections\": 0,"
|
||||
" \"total_connections\": 0,"
|
||||
" \"active_operations\": 0"
|
||||
" }"
|
||||
" }"
|
||||
" },"
|
||||
" {"
|
||||
" \"id\": \"server3\","
|
||||
" \"type\": \"servers\","
|
||||
" \"relationships\": {"
|
||||
" \"services\": {"
|
||||
" \"links\": {"
|
||||
" \"self\": \"http://localhost:8989/v1/services/\""
|
||||
" },"
|
||||
" \"data\": ["
|
||||
" {"
|
||||
" \"id\": \"RW-Split-Router\","
|
||||
" \"type\": \"services\""
|
||||
" },"
|
||||
" {"
|
||||
" \"id\": \"SchemaRouter-Router\","
|
||||
" \"type\": \"services\""
|
||||
" },"
|
||||
" {"
|
||||
" \"id\": \"RW-Split-Hint-Router\","
|
||||
" \"type\": \"services\""
|
||||
" }"
|
||||
" ]"
|
||||
" },"
|
||||
" \"monitors\": {"
|
||||
" \"links\": {"
|
||||
" \"self\": \"http://localhost:8989/v1/monitors/\""
|
||||
" },"
|
||||
" \"data\": ["
|
||||
" {"
|
||||
" \"id\": \"MySQL-Monitor\","
|
||||
" \"type\": \"monitors\""
|
||||
" }"
|
||||
" ]"
|
||||
" }"
|
||||
" },"
|
||||
" \"attributes\": {"
|
||||
" \"parameters\": {"
|
||||
" \"address\": \"127.0.0.1\","
|
||||
" \"port\": 3002,"
|
||||
" \"protocol\": \"MySQLBackend\""
|
||||
" },"
|
||||
" \"status\": \"Slave, Running\","
|
||||
" \"version_string\": \"10.1.19-MariaDB-1~jessie\","
|
||||
" \"node_id\": 3002,"
|
||||
" \"master_id\": 3000,"
|
||||
" \"replication_depth\": 1,"
|
||||
" \"slaves\": [],"
|
||||
" \"statictics\": {"
|
||||
" \"connections\": 0,"
|
||||
" \"total_connections\": 0,"
|
||||
" \"active_operations\": 0"
|
||||
" }"
|
||||
" }"
|
||||
" },"
|
||||
" {"
|
||||
" \"id\": \"server4\","
|
||||
" \"type\": \"servers\","
|
||||
" \"relationships\": {"
|
||||
" \"services\": {"
|
||||
" \"links\": {"
|
||||
" \"self\": \"http://localhost:8989/v1/services/\""
|
||||
" },"
|
||||
" \"data\": ["
|
||||
" {"
|
||||
" \"id\": \"RW-Split-Router\","
|
||||
" \"type\": \"services\""
|
||||
" },"
|
||||
" {"
|
||||
" \"id\": \"SchemaRouter-Router\","
|
||||
" \"type\": \"services\""
|
||||
" },"
|
||||
" {"
|
||||
" \"id\": \"RW-Split-Hint-Router\","
|
||||
" \"type\": \"services\""
|
||||
" }"
|
||||
" ]"
|
||||
" },"
|
||||
" \"monitors\": {"
|
||||
" \"links\": {"
|
||||
" \"self\": \"http://localhost:8989/v1/monitors/\""
|
||||
" },"
|
||||
" \"data\": ["
|
||||
" {"
|
||||
" \"id\": \"MySQL-Monitor\","
|
||||
" \"type\": \"monitors\""
|
||||
" }"
|
||||
" ]"
|
||||
" }"
|
||||
" },"
|
||||
" \"attributes\": {"
|
||||
" \"parameters\": {"
|
||||
" \"address\": \"127.0.0.1\","
|
||||
" \"port\": 3003,"
|
||||
" \"protocol\": \"MySQLBackend\""
|
||||
" },"
|
||||
" \"status\": \"Slave, Running\","
|
||||
" \"version_string\": \"10.1.19-MariaDB-1~jessie\","
|
||||
" \"node_id\": 3003,"
|
||||
" \"master_id\": 3000,"
|
||||
" \"replication_depth\": 1,"
|
||||
" \"slaves\": [],"
|
||||
" \"statictics\": {"
|
||||
" \"connections\": 0,"
|
||||
" \"total_connections\": 0,"
|
||||
" \"active_operations\": 0"
|
||||
" }"
|
||||
" }"
|
||||
" }"
|
||||
" ]"
|
||||
"}";
|
||||
|
||||
int test1()
|
||||
{
|
||||
json_error_t err = {};
|
||||
json_t* json = json_loads(test1_json, 0, &err);
|
||||
|
||||
ss_dassert(json);
|
||||
|
||||
ss_dassert(mxs_json_pointer(json, "") == json);
|
||||
ss_dassert(mxs_json_pointer(json, "links") == json_object_get(json, "links"));
|
||||
ss_dassert(json_is_string(mxs_json_pointer(json, "links/self")));
|
||||
|
||||
ss_dassert(mxs_json_pointer(json, "data") == json_object_get(json, "data"));
|
||||
ss_dassert(json_is_array(mxs_json_pointer(json, "data")));
|
||||
|
||||
ss_dassert(json_is_object(mxs_json_pointer(json, "data/0")));
|
||||
ss_dassert(json_is_string(mxs_json_pointer(json, "data/0/id")));
|
||||
string s = json_string_value(mxs_json_pointer(json, "data/0/id"));
|
||||
ss_dassert(s == "server1");
|
||||
|
||||
ss_dassert(json_is_object(mxs_json_pointer(json, "data/1")));
|
||||
ss_dassert(json_is_string(mxs_json_pointer(json, "data/1/id")));
|
||||
s = json_string_value(mxs_json_pointer(json, "data/1/id"));
|
||||
ss_dassert(s == "server2");
|
||||
|
||||
ss_dassert(json_is_object(mxs_json_pointer(json, "data/0/attributes")));
|
||||
ss_dassert(json_is_object(mxs_json_pointer(json, "data/0/attributes/parameters")));
|
||||
ss_dassert(json_is_integer(mxs_json_pointer(json, "data/0/attributes/parameters/port")));
|
||||
int i = json_integer_value(mxs_json_pointer(json, "data/0/attributes/parameters/port"));
|
||||
ss_dassert(i == 3000);
|
||||
|
||||
ss_dassert(json_is_array(mxs_json_pointer(json, "data/0/attributes/slaves")));
|
||||
ss_dassert(json_array_size(mxs_json_pointer(json, "data/0/attributes/slaves")) == 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
test1();
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user