diff --git a/parson.c b/parson.c index 8983166..4727324 100644 --- a/parson.c +++ b/parson.c @@ -1003,6 +1003,24 @@ JSON_Value * json_object_get_value_at(const JSON_Object *object, size_t index) { return object->values[index]; } +int json_object_has_value (const JSON_Object *object, const char *name) { + return json_object_get_value(object, name) != NULL; +} + +int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type) { + JSON_Value *val = json_object_get_value(object, name); + return val != NULL && json_value_get_type(val) == type; +} + +int json_object_dothas_value (const JSON_Object *object, const char *name) { + return json_object_dotget_value(object, name) != NULL; +} + +int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type) { + JSON_Value *val = json_object_dotget_value(object, name); + return val != NULL && json_value_get_type(val) == type; +} + /* JSON Array API */ JSON_Value * json_array_get_value(const JSON_Array *array, size_t index) { if (array == NULL || index >= json_array_get_count(array)) diff --git a/parson.h b/parson.h index 1be1aa4..6a89982 100644 --- a/parson.h +++ b/parson.h @@ -129,6 +129,14 @@ size_t json_object_get_count (const JSON_Object *object); const char * json_object_get_name (const JSON_Object *object, size_t index); JSON_Value * json_object_get_value_at(const JSON_Object *object, size_t index); +/* Functions to check if object has a value with a specific name. Returned value is 1 if object has + * a value and 0 if it doesn't. dothas functions behave exactly like dotget functions. */ +int json_object_has_value (const JSON_Object *object, const char *name); +int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type); + +int json_object_dothas_value (const JSON_Object *object, const char *name); +int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type); + /* Creates new name-value pair or frees and replaces old value with a new one. * json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */ JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value); diff --git a/tests.c b/tests.c index 8a658a5..819711d 100644 --- a/tests.c +++ b/tests.c @@ -119,10 +119,42 @@ void test_suite_2(JSON_Value *root_value) { TEST(root_value); TEST(json_value_get_type(root_value) == JSONObject); root_object = json_value_get_object(root_value); + + TEST(json_object_has_value(root_object, "string")); + TEST(!json_object_has_value(root_object, "_string")); + TEST(json_object_has_value_of_type(root_object, "object", JSONObject)); + TEST(!json_object_has_value_of_type(root_object, "string array", JSONObject)); + TEST(json_object_has_value_of_type(root_object, "string array", JSONArray)); + TEST(!json_object_has_value_of_type(root_object, "object", JSONArray)); + TEST(json_object_has_value_of_type(root_object, "string", JSONString)); + TEST(!json_object_has_value_of_type(root_object, "positive one", JSONString)); + TEST(json_object_has_value_of_type(root_object, "positive one", JSONNumber)); + TEST(!json_object_has_value_of_type(root_object, "string", JSONNumber)); + TEST(json_object_has_value_of_type(root_object, "boolean true", JSONBoolean)); + TEST(!json_object_has_value_of_type(root_object, "positive one", JSONBoolean)); + TEST(json_object_has_value_of_type(root_object, "null", JSONNull)); + TEST(!json_object_has_value_of_type(root_object, "object", JSONNull)); + + TEST(json_object_dothas_value(root_object, "object.nested array")); + TEST(!json_object_dothas_value(root_object, "_object.nested array")); + TEST(json_object_dothas_value_of_type(root_object, "object.nested object", JSONObject)); + TEST(!json_object_dothas_value_of_type(root_object, "object.nested array", JSONObject)); + TEST(json_object_dothas_value_of_type(root_object, "object.nested array", JSONArray)); + TEST(!json_object_dothas_value_of_type(root_object, "object.nested object", JSONArray)); + TEST(json_object_dothas_value_of_type(root_object, "object.nested string", JSONString)); + TEST(!json_object_dothas_value_of_type(root_object, "object.nested number", JSONString)); + TEST(json_object_dothas_value_of_type(root_object, "object.nested number", JSONNumber)); + TEST(!json_object_dothas_value_of_type(root_object, "_object.nested whatever", JSONNumber)); + TEST(json_object_dothas_value_of_type(root_object, "object.nested true", JSONBoolean)); + TEST(!json_object_dothas_value_of_type(root_object, "object.nested number", JSONBoolean)); + TEST(json_object_dothas_value_of_type(root_object, "object.nested null", JSONNull)); + TEST(!json_object_dothas_value_of_type(root_object, "object.nested object", JSONNull)); + TEST(STREQ(json_object_get_string(root_object, "string"), "lorem ipsum")); TEST(STREQ(json_object_get_string(root_object, "utf string"), "lorem ipsum")); TEST(STREQ(json_object_get_string(root_object, "utf-8 string"), "あいうえお")); TEST(STREQ(json_object_get_string(root_object, "surrogate string"), "lorem𝄞ipsum𝍧lorem")); + TEST(json_object_get_number(root_object, "positive one") == 1.0); TEST(json_object_get_number(root_object, "negative one") == -1.0); TEST(fabs(json_object_get_number(root_object, "hard to parse number") - (-0.000314)) < EPSILON); @@ -166,7 +198,7 @@ void test_suite_2(JSON_Value *root_value) { TEST(STREQ(json_array_get_string(array, 0), "lorem")); TEST(STREQ(json_array_get_string(array, 1), "ipsum")); } - TEST(json_object_dotget_boolean(root_object, "nested true")); + TEST(json_object_dotget_boolean(root_object, "object.nested true") == 1); TEST(STREQ(json_object_get_string(root_object, "/**/"), "comment")); TEST(STREQ(json_object_get_string(root_object, "//"), "comment")); diff --git a/tests/test_2.txt b/tests/test_2.txt index f743581..b8c7350 100644 --- a/tests/test_2.txt +++ b/tests/test_2.txt @@ -1,29 +1,31 @@ { - "string" : "lorem ipsum", - "utf string" : "\u006corem\u0020ipsum", + "string" : "lorem ipsum", + "utf string" : "\u006corem\u0020ipsum", "utf-8 string": "あいうえお", "surrogate string": "lorem\uD834\uDD1Eipsum\uD834\uDF67lorem", - "positive one" : 1, - "negative one" : -1, - "pi" : 3.14, - "hard to parse number" : -3.14e-4, - "boolean true" : true, - "boolean false" : false, - "null" : null, - "string array" : ["lorem", "ipsum"], - "x^2 array" : [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100], - "/*" : null, - "object" : { "nested string" : "str", - "nested true" : true, - "nested false" : false, - "nested null" : null, - "nested number" : 123, - "nested array" : ["lorem", "ipsum"] }, - "*/" : null, - "/**/" : "comment", - "//" : "comment", - "url" : "https:\/\/www.example.com\/search?q=12345", - "escaped chars" : "\" \\ \/", - "empty object" : {}, - "empty array" : [] + "positive one" : 1, + "negative one" : -1, + "pi" : 3.14, + "hard to parse number" : -3.14e-4, + "boolean true" : true, + "boolean false" : false, + "null" : null, + "string array" : ["lorem", "ipsum"], + "x^2 array" : [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100], + "/*" : null, + "object" : { "nested string" : "str", + "nested true" : true, + "nested false" : false, + "nested null" : null, + "nested number" : 123, + "nested array" : ["lorem", "ipsum"], + "nested object" : {"lorem": "ipsum"} + }, + "*/" : null, + "/**/" : "comment", + "//" : "comment", + "url" : "https:\/\/www.example.com\/search?q=12345", + "escaped chars" : "\" \\ \/", + "empty object" : {}, + "empty array" : [] } diff --git a/tests/test_2_comments.txt b/tests/test_2_comments.txt index f275e15..5ecf129 100644 --- a/tests/test_2_comments.txt +++ b/tests/test_2_comments.txt @@ -22,11 +22,13 @@ */ "/*" : null, "object" : { "nested string" : "str", - "nested true" : /* lorem ipsum */ true, + "nested true" : /* lorem ipsum */ true, "nested false" : false, "nested null" : null, // lorem ipsum "nested number" : 123, - "nested array" : ["lorem", "ipsum"] }, + "nested array" : ["lorem", "ipsum"], + "nested object" : {"lorem": "ipsum"} + }, "*/" : null, "/**/" : "comment", "//" : "comment",