Add json parse and stringify function to jerryscript c api (#2243)
JerryScript-DCO-1.0-Signed-off-by: Zsolt Raduska rzsolt@inf.u-szeged.hu
This commit is contained in:
committed by
László Langó
parent
0476523f1a
commit
78bd11e732
@@ -5921,3 +5921,73 @@ jerry_value_t jerry_get_typedarray_buffer (jerry_value_t value,
|
||||
**See also**
|
||||
|
||||
- [jerry_create_typedarray](#jerry_create_typedarray)
|
||||
|
||||
# JSON functions
|
||||
|
||||
## jerry_json_parse
|
||||
|
||||
**Summary**
|
||||
|
||||
Returns the same result as JSON.parse ecmascript function.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t jerry_json_parse (const jerry_char_t *string_p, jerry_size_t string_size)
|
||||
```
|
||||
|
||||
- `string_p` - a JSON string
|
||||
- `string_size` - size of the string
|
||||
- return
|
||||
- jerry_value_t containing the same as json.parse()
|
||||
- jerry_value_t containing error massage
|
||||
|
||||
**Example**
|
||||
|
||||
```c
|
||||
{
|
||||
const char *data = "{\"name\": \"John\", \"age\": 5}";
|
||||
jerry_size_t str_length = (jerry_size_t)strlen (data);
|
||||
jerry_value_t parsed_json = jerry_json_parse ((jerry_char_t*)data, str_length);
|
||||
|
||||
// parsed_json now conatins all data stored in data_in_json
|
||||
|
||||
jerry_release_value (parsed_json);
|
||||
}
|
||||
```
|
||||
|
||||
## jerry_stringify
|
||||
|
||||
**Summary**
|
||||
|
||||
Returns the same value as JSON.stringify() ecmascript function.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t jerry_json_stringfy (const jerry_value_t object_to_stringify)
|
||||
```
|
||||
|
||||
- `object_to_stringify` - a jerry_value_t object to stringify
|
||||
- return
|
||||
- jerry_value_t containing the same as json.stringify()
|
||||
- jerry_value_t containing error massage
|
||||
|
||||
**Example**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t obj = jerry_create_object ();
|
||||
jerry_value_t key = jerry_create_string ((const jerry_char_t *) "name");
|
||||
jerry_value_t value = jerry_create_string ((const jerry_char_t *) "John");
|
||||
jerry_set_property (obj, key, value);
|
||||
jerry_value_t stringified = jerry_json_stringfy (obj);
|
||||
|
||||
//stringified now contains a json formated string
|
||||
|
||||
jerry_release_value (obj);
|
||||
jerry_release_value (key);
|
||||
jerry_release_value (value);
|
||||
jerry_release_value (stringified);
|
||||
}
|
||||
```
|
||||
@@ -3412,6 +3412,63 @@ jerry_get_typedarray_buffer (jerry_value_t value, /**< TypedArray to get the arr
|
||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
} /* jerry_get_typedarray_buffer */
|
||||
|
||||
/**
|
||||
* Create an object from JSON
|
||||
*
|
||||
* Note:
|
||||
* The returned value must be freed with jerry_release_value
|
||||
* @return jerry_value_t from json formated string or an error massage
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_json_parse (const jerry_char_t *string_p, /**< json string */
|
||||
jerry_size_t string_size) /**< json string size */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#ifndef CONFIG_DISABLE_JSON_BUILTIN
|
||||
ecma_value_t ret_value = ecma_builtin_json_parse_buffer (string_p, string_size);
|
||||
|
||||
if (ecma_is_value_undefined (ret_value))
|
||||
{
|
||||
ret_value = jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("JSON string parse error.")));
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
#else /* CONFIG_DISABLE_JSON_BUILTIN */
|
||||
JERRY_UNUSED (string_p);
|
||||
JERRY_UNUSED (string_size);
|
||||
|
||||
return jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("The JSON has been disabled.")));
|
||||
#endif /* !CONFIG_DISABLE_JSON_BUILTIN */
|
||||
} /* jerry_json_parse */
|
||||
|
||||
/**
|
||||
* Create a Json formated string from an object
|
||||
*
|
||||
* Note:
|
||||
* The returned value must be freed with jerry_release_value
|
||||
* @return json formated jerry_value_t or an error massage
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_json_stringfy (const jerry_value_t object_to_stringify) /**< a jerry_object_t to stringify */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
#ifndef CONFIG_DISABLE_JSON_BUILTIN
|
||||
ecma_value_t ret_value = ecma_builtin_json_string_from_object (object_to_stringify);
|
||||
|
||||
if (ecma_is_value_undefined (ret_value))
|
||||
{
|
||||
ret_value = jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("JSON stringify error.")));
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
#else /* CONFIG_DISABLE_JSON_BUILTIN */
|
||||
JERRY_UNUSED (object_to_stringify);
|
||||
|
||||
return jerry_throw (ecma_raise_syntax_error (ECMA_ERR_MSG ("The JSON has been disabled.")));
|
||||
#endif /* !CONFIG_DISABLE_JSON_BUILTIN */
|
||||
} /* jerry_json_stringfy */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "ecma-builtin-helpers.h"
|
||||
#include "lit-char-helpers.h"
|
||||
|
||||
#ifndef CONFIG_DISABLE_JSON_BUILTIN
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
@@ -221,6 +223,8 @@ ecma_builtin_helper_json_create_non_formatted_json (lit_utf8_byte_t left_bracket
|
||||
return ecma_make_string_value (result_str_p);
|
||||
} /* ecma_builtin_helper_json_create_non_formatted_json */
|
||||
|
||||
#endif /* !CONFIG_DISABLE_JSON_BUILTIN */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@@ -152,6 +152,9 @@ typedef struct
|
||||
ecma_object_t *replacer_function_p;
|
||||
} ecma_json_stringify_context_t;
|
||||
|
||||
ecma_value_t ecma_builtin_json_parse_buffer (const lit_utf8_byte_t * str_start_p,
|
||||
lit_utf8_size_t string_size);
|
||||
ecma_value_t ecma_builtin_json_string_from_object (const ecma_value_t arg1);
|
||||
bool ecma_json_has_object_in_stack (ecma_json_occurence_stack_item_t *stack_p, ecma_object_t *object_p);
|
||||
bool ecma_has_string_value_in_collection (ecma_collection_header_t *collection_p, ecma_value_t string_value);
|
||||
|
||||
|
||||
@@ -805,6 +805,35 @@ ecma_builtin_json_walk (ecma_object_t *reviver_p, /**< reviver function */
|
||||
return ret_value;
|
||||
} /* ecma_builtin_json_walk */
|
||||
|
||||
/**
|
||||
* Function to set a string token from the given arguments, fills its fields and advances the string pointer.
|
||||
*
|
||||
* @return ecma_value_t containing an object or an error massage
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_builtin_json_parse_buffer (const lit_utf8_byte_t * str_start_p, /**< String to parse */
|
||||
lit_utf8_size_t string_size) /**< size of the string */
|
||||
{
|
||||
ecma_json_token_t token;
|
||||
token.current_p = str_start_p;
|
||||
token.end_p = str_start_p + string_size;
|
||||
|
||||
ecma_value_t final_result = ecma_builtin_json_parse_value (&token);
|
||||
|
||||
if (!ecma_is_value_undefined (final_result))
|
||||
{
|
||||
ecma_builtin_json_parse_next_token (&token, false);
|
||||
|
||||
if (token.type != end_token)
|
||||
{
|
||||
ecma_free_value (final_result);
|
||||
final_result = ECMA_VALUE_UNDEFINED;
|
||||
}
|
||||
}
|
||||
return final_result;
|
||||
} /*ecma_builtin_json_parse_buffer*/
|
||||
|
||||
/**
|
||||
* The JSON object's 'parse' routine
|
||||
*
|
||||
@@ -830,22 +859,7 @@ ecma_builtin_json_parse (ecma_value_t this_arg, /**< 'this' argument */
|
||||
|
||||
ECMA_STRING_TO_UTF8_STRING (string_p, str_start_p, string_size);
|
||||
|
||||
ecma_json_token_t token;
|
||||
token.current_p = str_start_p;
|
||||
token.end_p = str_start_p + string_size;
|
||||
|
||||
ecma_value_t final_result = ecma_builtin_json_parse_value (&token);
|
||||
|
||||
if (!ecma_is_value_undefined (final_result))
|
||||
{
|
||||
ecma_builtin_json_parse_next_token (&token, false);
|
||||
|
||||
if (token.type != end_token)
|
||||
{
|
||||
ecma_free_value (final_result);
|
||||
final_result = ECMA_VALUE_UNDEFINED;
|
||||
}
|
||||
}
|
||||
ecma_value_t final_result = ecma_builtin_json_parse_buffer (str_start_p, string_size);
|
||||
|
||||
if (ecma_is_value_undefined (final_result))
|
||||
{
|
||||
@@ -892,6 +906,61 @@ ecma_builtin_json_object (ecma_object_t *obj_p, ecma_json_stringify_context_t *c
|
||||
static ecma_value_t
|
||||
ecma_builtin_json_array (ecma_object_t *obj_p, ecma_json_stringify_context_t *context_p);
|
||||
|
||||
/**
|
||||
* Helper function to stringify an object in JSON format representing an ecma_value.
|
||||
*
|
||||
* @return ecma_value_t string created from an abject formating by a given context
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*
|
||||
*/
|
||||
static ecma_value_t ecma_builtin_json_str_helper (const ecma_value_t arg1, /**< object argument */
|
||||
ecma_json_stringify_context_t context) /**< context argument */
|
||||
{
|
||||
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
|
||||
ecma_object_t *obj_wrapper_p = ecma_op_create_object_object_noarg ();
|
||||
ecma_string_t *empty_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);
|
||||
ecma_value_t put_comp_val = ecma_op_object_put (obj_wrapper_p,
|
||||
empty_str_p,
|
||||
arg1,
|
||||
false);
|
||||
JERRY_ASSERT (ecma_is_value_true (put_comp_val));
|
||||
ecma_free_value (put_comp_val);
|
||||
ECMA_TRY_CATCH (str_val,
|
||||
ecma_builtin_json_str (empty_str_p, obj_wrapper_p, &context),
|
||||
ret_value);
|
||||
ret_value = ecma_copy_value (str_val);
|
||||
ECMA_FINALIZE (str_val);
|
||||
ecma_free_value (put_comp_val);
|
||||
ecma_deref_ecma_string (empty_str_p);
|
||||
ecma_deref_object (obj_wrapper_p);
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_builtin_json_str_helper */
|
||||
|
||||
/**
|
||||
* Function to create a json formated string from an object
|
||||
*
|
||||
* @return ecma_value_t containing a json string
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_builtin_json_string_from_object (const ecma_value_t arg1) /**< object argument */
|
||||
{
|
||||
ecma_json_stringify_context_t context;
|
||||
context.occurence_stack_last_p = NULL;
|
||||
context.indent_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);
|
||||
context.property_list_p = ecma_new_values_collection ();
|
||||
context.replacer_function_p = NULL;
|
||||
context.gap_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);
|
||||
|
||||
ecma_value_t ret_value = ecma_builtin_json_str_helper (arg1, context);
|
||||
|
||||
ecma_deref_ecma_string (context.gap_str_p);
|
||||
ecma_deref_ecma_string (context.indent_str_p);
|
||||
ecma_free_values_collection (context.property_list_p, 0);
|
||||
return ret_value;
|
||||
} /*ecma_builtin_json_string_from_object*/
|
||||
|
||||
/**
|
||||
* The JSON object's 'stringify' routine
|
||||
*
|
||||
@@ -1119,28 +1188,7 @@ ecma_builtin_json_stringify (ecma_value_t this_arg, /**< 'this' argument */
|
||||
if (ecma_is_value_empty (ret_value))
|
||||
{
|
||||
/* 9. */
|
||||
ecma_object_t *obj_wrapper_p = ecma_op_create_object_object_noarg ();
|
||||
ecma_string_t *empty_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);
|
||||
|
||||
/* 10. */
|
||||
ecma_value_t put_comp_val = ecma_op_object_put (obj_wrapper_p,
|
||||
empty_str_p,
|
||||
arg1,
|
||||
false);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_true (put_comp_val));
|
||||
ecma_free_value (put_comp_val);
|
||||
|
||||
/* 11. */
|
||||
ECMA_TRY_CATCH (str_val,
|
||||
ecma_builtin_json_str (empty_str_p, obj_wrapper_p, &context),
|
||||
ret_value);
|
||||
|
||||
ret_value = ecma_copy_value (str_val);
|
||||
|
||||
ECMA_FINALIZE (str_val);
|
||||
|
||||
ecma_deref_object (obj_wrapper_p);
|
||||
ret_value = ecma_builtin_json_str_helper (arg1, context);
|
||||
}
|
||||
|
||||
ecma_deref_ecma_string (context.gap_str_p);
|
||||
|
||||
@@ -544,6 +544,8 @@ jerry_length_t jerry_get_typedarray_length (jerry_value_t value);
|
||||
jerry_value_t jerry_get_typedarray_buffer (jerry_value_t value,
|
||||
jerry_length_t *byte_offset,
|
||||
jerry_length_t *byte_length);
|
||||
jerry_value_t jerry_json_parse (const jerry_char_t *string_p, jerry_size_t string_size);
|
||||
jerry_value_t jerry_json_stringfy (const jerry_value_t object_to_stringify);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
||||
@@ -1139,6 +1139,48 @@ main (void)
|
||||
|
||||
jerry_release_value (args[1]);
|
||||
|
||||
{
|
||||
/*json parser check*/
|
||||
char data_check[]="John";
|
||||
jerry_value_t key = jerry_create_string ((const jerry_char_t *) "name");
|
||||
const char *data = "{\"name\": \"John\", \"age\": 5}";
|
||||
jerry_size_t str_length = (jerry_size_t) strlen (data);
|
||||
jerry_value_t parsed_json = jerry_json_parse ((jerry_char_t *) data, str_length);
|
||||
jerry_value_t has_prop_js = jerry_has_property (parsed_json, key);
|
||||
TEST_ASSERT (jerry_get_boolean_value (has_prop_js));
|
||||
jerry_release_value (has_prop_js);
|
||||
jerry_value_t parsed_data = jerry_get_property (parsed_json, key);
|
||||
TEST_ASSERT (jerry_value_is_string (parsed_data)== true);
|
||||
jerry_size_t buff_size = (jerry_size_t) jerry_get_string_length (parsed_data);
|
||||
char buff[jerry_get_string_length (parsed_data)];
|
||||
jerry_char_t *buff_p = (jerry_char_t *) buff;
|
||||
jerry_string_to_char_buffer (parsed_data, buff_p, buff_size);
|
||||
buff[buff_size] = '\0';
|
||||
TEST_ASSERT (strcmp ((const char *) data_check, (const char *) buff) == false);
|
||||
jerry_release_value (parsed_json);
|
||||
jerry_release_value (key);
|
||||
jerry_release_value (parsed_data);
|
||||
}
|
||||
|
||||
/*json stringify test*/
|
||||
{
|
||||
jerry_value_t obj = jerry_create_object ();
|
||||
char check_value[] = "{\"name\":\"John\"}";
|
||||
jerry_value_t key = jerry_create_string ((const jerry_char_t *) "name");
|
||||
jerry_value_t value = jerry_create_string ((const jerry_char_t *) "John");
|
||||
jerry_set_property (obj, key, value);
|
||||
jerry_value_t stringified = jerry_json_stringfy (obj);
|
||||
TEST_ASSERT (jerry_value_is_string (stringified));
|
||||
char buff[jerry_get_string_length (stringified)];
|
||||
jerry_string_to_char_buffer (stringified, (jerry_char_t *) buff,
|
||||
(jerry_size_t) jerry_get_string_length (stringified));
|
||||
buff[jerry_get_string_length (stringified)] = '\0';
|
||||
TEST_ASSERT (strcmp ((const char *) check_value, (const char *) buff) == 0);
|
||||
jerry_release_value (stringified);
|
||||
jerry_release_value (obj);
|
||||
jerry_release_value (key);
|
||||
jerry_release_value (value);
|
||||
}
|
||||
jerry_cleanup ();
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user