diff options
author | Sergei Golubchik <serg@mariadb.org> | 2018-11-28 18:16:46 +0100 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2018-12-12 00:31:43 +0100 |
commit | d68d7e50f928f7966f21524b4247a0a54d09a6d1 (patch) | |
tree | 01bedbae211cde39ee3ec9f040b8aa472ab02270 | |
parent | a76aadf7bc54e750e2474a080777e346ddbffc0d (diff) | |
download | mariadb-git-d68d7e50f928f7966f21524b4247a0a54d09a6d1.tar.gz |
json helpers
-rw-r--r-- | include/json_lib.h | 6 | ||||
-rw-r--r-- | sql/item_jsonfunc.cc | 8 | ||||
-rw-r--r-- | strings/json_lib.c | 81 |
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; +} |