summaryrefslogtreecommitdiffstats
path: root/src/libnetdata/json
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-11-25 17:33:56 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-11-25 17:34:10 +0000
commit83ba6762cc43d9db581b979bb5e3445669e46cc2 (patch)
tree2e69833b43f791ed253a7a20318b767ebe56cdb8 /src/libnetdata/json
parentReleasing debian version 1.47.5-1. (diff)
downloadnetdata-83ba6762cc43d9db581b979bb5e3445669e46cc2.tar.xz
netdata-83ba6762cc43d9db581b979bb5e3445669e46cc2.zip
Merging upstream version 2.0.3+dfsg (Closes: #923993, #1042533, #1045145).
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/libnetdata/json')
-rw-r--r--src/libnetdata/json/README.md9
-rw-r--r--src/libnetdata/json/json-c-parser-inline.c52
-rw-r--r--src/libnetdata/json/json-c-parser-inline.h69
3 files changed, 117 insertions, 13 deletions
diff --git a/src/libnetdata/json/README.md b/src/libnetdata/json/README.md
index 9ae5ff382..21cd42a79 100644
--- a/src/libnetdata/json/README.md
+++ b/src/libnetdata/json/README.md
@@ -1,12 +1,3 @@
-<!--
-title: "json"
-custom_edit_url: https://github.com/netdata/netdata/edit/master/src/libnetdata/json/README.md
-sidebar_label: "json"
-learn_status: "Published"
-learn_topic_type: "Tasks"
-learn_rel_path: "Developers/libnetdata"
--->
-
# json
`json` contains a parser for json strings, based on `jsmn` (<https://github.com/zserge/jsmn>), but case you have installed the JSON-C library, the installation script will prefer it, you can also force its use with `--enable-jsonc` in the compilation time.
diff --git a/src/libnetdata/json/json-c-parser-inline.c b/src/libnetdata/json/json-c-parser-inline.c
new file mode 100644
index 000000000..a17847a3e
--- /dev/null
+++ b/src/libnetdata/json/json-c-parser-inline.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "../libnetdata.h"
+
+int rrd_call_function_error(BUFFER *wb, const char *msg, int code) {
+ buffer_reset(wb);
+ buffer_json_initialize(wb, "\"", "\"", 0, true, BUFFER_JSON_OPTIONS_MINIFY);
+ buffer_json_member_add_int64(wb, "status", code);
+ buffer_json_member_add_string(wb, "error_message", msg);
+ buffer_json_finalize(wb);
+ wb->date = now_realtime_sec();
+ wb->expires = wb->date + 1;
+ wb->response_code = code;
+ return code;
+}
+
+struct json_object *json_parse_function_payload_or_error(BUFFER *output, BUFFER *payload, int *code, json_parse_function_payload_t cb, void *cb_data) {
+ if(!payload || !buffer_strlen(payload)) {
+ *code = rrd_call_function_error(output, "No payload given, but a payload is required for this feature.", HTTP_RESP_BAD_REQUEST);
+ return NULL;
+ }
+
+ struct json_tokener *tokener = json_tokener_new();
+ if (!tokener) {
+ *code = rrd_call_function_error(output, "Failed to initialize json parser.", HTTP_RESP_INTERNAL_SERVER_ERROR);
+ return NULL;
+ }
+
+ struct json_object *jobj = json_tokener_parse_ex(tokener, buffer_tostring(payload), (int)buffer_strlen(payload));
+ if (json_tokener_get_error(tokener) != json_tokener_success) {
+ const char *error_msg = json_tokener_error_desc(json_tokener_get_error(tokener));
+ char tmp[strlen(error_msg) + 100];
+ snprintf(tmp, sizeof(tmp), "JSON parser failed: %s", error_msg);
+ json_tokener_free(tokener);
+ *code = rrd_call_function_error(output, tmp, HTTP_RESP_INTERNAL_SERVER_ERROR);
+ return NULL;
+ }
+ json_tokener_free(tokener);
+
+ CLEAN_BUFFER *error = buffer_create(0, NULL);
+ if(!cb(jobj, "", cb_data, error)) {
+ char tmp[buffer_strlen(error) + 100];
+ snprintfz(tmp, sizeof(tmp), "JSON parser failed: %s", buffer_tostring(error));
+ *code = rrd_call_function_error(output, tmp, HTTP_RESP_BAD_REQUEST);
+ json_object_put(jobj);
+ return NULL;
+ }
+
+ *code = HTTP_RESP_OK;
+
+ return jobj;
+}
diff --git a/src/libnetdata/json/json-c-parser-inline.h b/src/libnetdata/json/json-c-parser-inline.h
index c1d60ca45..e51cb232e 100644
--- a/src/libnetdata/json/json-c-parser-inline.h
+++ b/src/libnetdata/json/json-c-parser-inline.h
@@ -25,6 +25,45 @@
} \
} while(0)
+#define JSONC_PARSE_TXT2STRDUPZ_OR_ERROR_AND_RETURN(jobj, path, member, dst, error, required) do { \
+ json_object *_j; \
+ if (json_object_object_get_ex(jobj, member, &_j) && json_object_is_type(_j, json_type_string)) { \
+ freez((void *)dst); \
+ dst = strdupz(json_object_get_string(_j)); \
+ } \
+ else if(required) { \
+ buffer_sprintf(error, "missing or invalid type for '%s.%s' string", path, member); \
+ return false; \
+ } \
+} while(0)
+
+#define JSONC_PARSE_TXT2UUID_OR_ERROR_AND_RETURN(jobj, path, member, dst, error, required) do { \
+ json_object *_j; \
+ if (json_object_object_get_ex(jobj, member, &_j)) { \
+ if (json_object_is_type(_j, json_type_string)) { \
+ if (uuid_parse(json_object_get_string(_j), dst) != 0) { \
+ if(required) { \
+ buffer_sprintf(error, "invalid UUID '%s.%s'", path, member); \
+ return false; \
+ } \
+ else \
+ uuid_clear(dst); \
+ } \
+ } \
+ else if (json_object_is_type(_j, json_type_null)) { \
+ uuid_clear(dst); \
+ } \
+ else if (required) { \
+ buffer_sprintf(error, "expected UUID or null '%s.%s'", path, member); \
+ return false; \
+ } \
+ } \
+ else if (required) { \
+ buffer_sprintf(error, "missing UUID '%s.%s'", path, member); \
+ return false; \
+ } \
+} while(0)
+
#define JSONC_PARSE_TXT2BUFFER_OR_ERROR_AND_RETURN(jobj, path, member, dst, error, required) do { \
json_object *_j; \
if (json_object_object_get_ex(jobj, member, &_j) && json_object_is_type(_j, json_type_string)) { \
@@ -111,7 +150,6 @@
} \
} while(0)
-
#define JSONC_PARSE_TXT2ENUM_OR_ERROR_AND_RETURN(jobj, path, member, converter, dst, error, required) do { \
json_object *_j; \
if (json_object_object_get_ex(jobj, member, &_j) && json_object_is_type(_j, json_type_string)) \
@@ -122,11 +160,11 @@
} \
} while(0)
-#define JSONC_PARSE_INT_OR_ERROR_AND_RETURN(jobj, path, member, dst, error, required) do { \
+#define JSONC_PARSE_INT64_OR_ERROR_AND_RETURN(jobj, path, member, dst, error, required) do { \
json_object *_j; \
if (json_object_object_get_ex(jobj, member, &_j)) { \
if (_j != NULL && json_object_is_type(_j, json_type_int)) \
- dst = json_object_get_int(_j); \
+ dst = json_object_get_int64(_j); \
else if (_j != NULL && json_object_is_type(_j, json_type_double)) \
dst = (typeof(dst))json_object_get_double(_j); \
else if (_j == NULL) \
@@ -136,7 +174,26 @@
return false; \
} \
} else if(required) { \
- buffer_sprintf(error, "missing or invalid type (expected int value or null) for '%s.%s'", path, member); \
+ buffer_sprintf(error, "missing or invalid type (expected int value or null) for '%s.%s'", path, member);\
+ return false; \
+ } \
+} while(0)
+
+#define JSONC_PARSE_UINT64_OR_ERROR_AND_RETURN(jobj, path, member, dst, error, required) do { \
+ json_object *_j; \
+ if (json_object_object_get_ex(jobj, member, &_j)) { \
+ if (_j != NULL && json_object_is_type(_j, json_type_int)) \
+ dst = json_object_get_uint64(_j); \
+ else if (_j != NULL && json_object_is_type(_j, json_type_double)) \
+ dst = (typeof(dst))json_object_get_double(_j); \
+ else if (_j == NULL) \
+ dst = 0; \
+ else { \
+ buffer_sprintf(error, "not supported type (expected int) for '%s.%s'", path, member); \
+ return false; \
+ } \
+ } else if(required) { \
+ buffer_sprintf(error, "missing or invalid type (expected int value or null) for '%s.%s'", path, member);\
return false; \
} \
} while(0)
@@ -174,4 +231,8 @@
} \
} while(0)
+typedef bool (*json_parse_function_payload_t)(json_object *jobj, const char *path, void *data, BUFFER *error);
+int rrd_call_function_error(BUFFER *wb, const char *msg, int code);
+struct json_object *json_parse_function_payload_or_error(BUFFER *output, BUFFER *payload, int *code, json_parse_function_payload_t cb, void *cb_data);
+
#endif //NETDATA_JSON_C_PARSER_INLINE_H