summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2018-11-28 18:16:46 +0100
committerSergei Golubchik <serg@mariadb.org>2018-12-12 00:31:43 +0100
commitd68d7e50f928f7966f21524b4247a0a54d09a6d1 (patch)
tree01bedbae211cde39ee3ec9f040b8aa472ab02270
parenta76aadf7bc54e750e2474a080777e346ddbffc0d (diff)
downloadmariadb-git-d68d7e50f928f7966f21524b4247a0a54d09a6d1.tar.gz
json helpers
-rw-r--r--include/json_lib.h6
-rw-r--r--sql/item_jsonfunc.cc8
-rw-r--r--strings/json_lib.c81
3 files changed, 87 insertions, 8 deletions
diff --git a/include/json_lib.h b/include/json_lib.h
index 87b2688c850..0f8cff79a32 100644
--- a/include/json_lib.h
+++ b/include/json_lib.h
@@ -423,10 +423,14 @@ int json_path_parts_compare(
int json_path_compare(const json_path_t *a, const json_path_t *b,
enum json_value_types vt);
+int json_valid(const char *js, size_t js_len, CHARSET_INFO *cs);
+int json_get_object_by_key(const char *js, size_t js_len,
+ const char *key, size_t key_len,
+ enum json_value_types *value_type,
+ const char **value_start, size_t *value_len);
#ifdef __cplusplus
}
#endif
#endif /* JSON_LIB_INCLUDED */
-
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index 31d5dd50b35..54bdadc3a32 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -374,17 +374,11 @@ static int path_setup_nwc(json_path_t *p, CHARSET_INFO *i_cs,
longlong Item_func_json_valid::val_int()
{
String *js= args[0]->val_json(&tmp_value);
- json_engine_t je;
if ((null_value= args[0]->null_value))
return 0;
- json_scan_start(&je, js->charset(), (const uchar *) js->ptr(),
- (const uchar *) js->ptr()+js->length());
-
- while (json_scan_next(&je) == 0) {}
-
- return je.s.error == 0;
+ return json_valid(js->ptr(), js->length(), js->charset());
}
diff --git a/strings/json_lib.c b/strings/json_lib.c
index e3727368025..bc93601ff05 100644
--- a/strings/json_lib.c
+++ b/strings/json_lib.c
@@ -1877,4 +1877,85 @@ enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey
return JSV_NOTHING;
}
+/** Simple json lookup for a value by the key.
+
+ Only supports flat json objects.
+ Does not look inside nested objects.
+ Does not process complex path expressions.
+
+ @param js [in] json to search in
+ @param js_len [in] - " -
+ @param key [in] key to search for
+ @param key_len [in] - " -
+ @param value_type [out] type of the value found or 0 if not found
+ @param value_start [out] pointer into js (value or closing })
+ @param value_len [out] length of the value found or number of keys
+
+ @retval 0 - success
+ @retval 1 - error (invalid json)
+*/
+int json_get_object_by_key(const char *js, size_t js_len,
+ const char *key, size_t key_len,
+ enum json_value_types *value_type,
+ const char **value_start, size_t *value_len)
+{
+ json_engine_t je;
+ json_string_t key_name;
+ int n_keys= 0;
+
+ json_string_set_cs(&key_name, &my_charset_utf8mb4_bin);
+ json_scan_start(&je, &my_charset_utf8mb4_bin,(const uchar *) js,
+ (const uchar *) js + js_len);
+
+ if (json_read_value(&je) ||
+ je.value_type != JSON_VALUE_OBJECT)
+ goto err_return;
+
+ while (!json_scan_next(&je))
+ {
+ switch (je.state)
+ {
+ case JST_KEY:
+ n_keys++;
+ json_string_set_str(&key_name, (const uchar *) key,
+ (const uchar *) key + key_len);
+ if (!json_key_matches(&je, &key_name))
+ {
+ if (json_skip_key(&je))
+ goto err_return;
+ }
+ else
+ {
+ if (json_read_value(&je))
+ goto err_return;
+ *value_type= je.value_type;
+ *value_start= (const char *) je.value;
+ *value_len= je.value_len;
+ return 0;
+ }
+ break;
+
+ case JST_OBJ_END:
+ *value_type= (enum json_value_types) 0;
+ *value_start= (const char *) (je.s.c_str - je.sav_c_len);
+ *value_len= n_keys;
+ return 0;
+ }
+ }
+
+err_return:
+ return 1;
+}
+
+/** Check if json is valid (well-formed)
+
+ @retval 0 - success, json is well-formed
+ @retval 1 - error, json is invalid
+*/int json_valid(const char *js, size_t js_len, CHARSET_INFO *cs)
+{
+ json_engine_t je;
+ json_scan_start(&je, cs, (const uchar *) js, (const uchar *) js + js_len);
+ while (json_scan_next(&je) == 0) /* no-op */ ;
+ return je.s.error == 0;
+}