You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2026/09/27 20:49:24 UTC

(celix) 01/01: Add type checking to JSON serializer

This is an automated email from the ASF dual-hosted git repository.

pnoltes pushed a commit to branch feature/add-json-ser-type-checking
in repository https://gitbox.apache.org/repos/asf/celix.git

commit 0215c727b1e1a7992276fae5cd5fb95f0436877f
Author: Pepijn Noltes <pn...@apache.org>
AuthorDate: Sun Sep 27 22:48:09 2026 +0200

    Add type checking to JSON serializer
---
 libs/dfi/gtest/src/json_serializer_tests.cpp | 37 ++++++++++++
 libs/dfi/src/json_rpc.c                      |  7 ++-
 libs/dfi/src/json_serializer.c               | 84 ++++++++++++++++++++++++----
 libs/etcdlib/src/etcd.c                      |  2 +-
 4 files changed, 116 insertions(+), 14 deletions(-)

diff --git a/libs/dfi/gtest/src/json_serializer_tests.cpp b/libs/dfi/gtest/src/json_serializer_tests.cpp
index a5cbcd6e5..ca98523f1 100644
--- a/libs/dfi/gtest/src/json_serializer_tests.cpp
+++ b/libs/dfi/gtest/src/json_serializer_tests.cpp
@@ -556,6 +556,43 @@ static void parseTests() {
     celix_err_printErrors(stderr, nullptr, nullptr);
     dynType_destroy(type);
 
+    // integer type mismatch - string instead of integer
+    rc = dynType_parseWithStr("{I a}", nullptr, nullptr, &type);
+    ASSERT_EQ(0, rc);
+    inputStr = R"({"a":"not_an_integer"})";
+    rc = jsonSerializer_deserialize(type, inputStr, strlen(inputStr), &inst);
+    ASSERT_EQ(1, rc);
+    celix_err_printErrors(stderr, nullptr, nullptr);
+    dynType_destroy(type);
+
+    // double type mismatch - string instead of double
+    rc = dynType_parseWithStr("{D a}", nullptr, nullptr, &type);
+    ASSERT_EQ(0, rc);
+    inputStr = R"({"a":"not_a_double"})";
+    rc = jsonSerializer_deserialize(type, inputStr, strlen(inputStr), &inst);
+    ASSERT_EQ(1, rc);
+    celix_err_printErrors(stderr, nullptr, nullptr);
+    dynType_destroy(type);
+
+    // boolean type mismatch - integer instead of boolean
+    rc = dynType_parseWithStr("{Z a}", nullptr, nullptr, &type);
+    ASSERT_EQ(0, rc);
+    inputStr = R"({"a":1})";
+    rc = jsonSerializer_deserialize(type, inputStr, strlen(inputStr), &inst);
+    ASSERT_EQ(1, rc);
+    celix_err_printErrors(stderr, nullptr, nullptr);
+    dynType_destroy(type);
+
+    // float type mismatch - string instead of float
+    rc = dynType_parseWithStr("{F a}", nullptr, nullptr, &type);
+    ASSERT_EQ(0, rc);
+    inputStr = R"({"a":"not_a_float"})";
+    rc = jsonSerializer_deserialize(type, inputStr, strlen(inputStr), &inst);
+    ASSERT_EQ(1, rc);
+    celix_err_printErrors(stderr, nullptr, nullptr);
+    dynType_destroy(type);
+
+
     // extra member ("b") is allowed
     rc = dynType_parseWithStr("{t a}", nullptr, nullptr, &type);
     ASSERT_EQ(0, rc);
diff --git a/libs/dfi/src/json_rpc.c b/libs/dfi/src/json_rpc.c
index d7e9eb780..faae2beb7 100644
--- a/libs/dfi/src/json_rpc.c
+++ b/libs/dfi/src/json_rpc.c
@@ -270,7 +270,12 @@ int jsonRpc_handleReply(const dyn_function_type* func, const char* reply, void*
     rsError = json_object_get(replyJson, "e");
     if (rsError != NULL) {
         //get the invocation error of remote service function
-        *rsErrno = (int) json_integer_value(rsError);
+        if (json_is_integer(rsError)) {
+            *rsErrno = (int) json_integer_value(rsError);
+        } else {
+            celix_err_pushf("Expected json integer for error code but got %i", json_typeof(rsError));
+            return ERROR;
+        }
         return OK;
     }
     if (meta != DYN_FUNCTION_ARGUMENT_META__PRE_ALLOCATED_OUTPUT && meta != DYN_FUNCTION_ARGUMENT_META__OUTPUT) {
diff --git a/libs/dfi/src/json_serializer.c b/libs/dfi/src/json_serializer.c
index 453d6128f..58aec80ee 100644
--- a/libs/dfi/src/json_serializer.c
+++ b/libs/dfi/src/json_serializer.c
@@ -129,40 +129,100 @@ static int jsonSerializer_parseAny(const dyn_type* type, void* loc, json_t* val)
 
     switch (c) {
         case 'Z' :
-            *(bool*)loc = (bool) json_is_true(val);
+            if (json_is_boolean(val)) {
+                *(bool*)loc = (bool) json_is_true(val);
+            } else {
+                status = ERROR;
+                celix_err_pushf("Expected json boolean type but got %i", json_typeof(val));
+            }
             break;
         case 'F' :
-            *(float*)loc = (float) json_real_value(val);
+            if (json_is_real(val)) {
+                *(float*)loc = (float) json_real_value(val);
+            } else {
+                status = ERROR;
+                celix_err_pushf("Expected json real type but got %i", json_typeof(val));
+            }
             break;
         case 'D' :
-            *(double*)loc = json_real_value(val);
+            if (json_is_real(val)) {
+                *(double*)loc = json_real_value(val);
+            } else {
+                status = ERROR;
+                celix_err_pushf("Expected json real type but got %i", json_typeof(val));
+            }
             break;
         case 'N' :
-            *(int*)loc = (int) json_integer_value(val);
+            if (json_is_integer(val)) {
+                *(int*)loc = (int) json_integer_value(val);
+            } else {
+                status = ERROR;
+                celix_err_pushf("Expected json integer type but got %i", json_typeof(val));
+            }
             break;
         case 'B' :
-            *(char*)loc = (char) json_integer_value(val);
+            if (json_is_integer(val)) {
+                *(char*)loc = (char) json_integer_value(val);
+            } else {
+                status = ERROR;
+                celix_err_pushf("Expected json integer type but got %i", json_typeof(val));
+            }
             break;
         case 'S' :
-            *(int16_t*)loc = (int16_t) json_integer_value(val);
+            if (json_is_integer(val)) {
+                *(int16_t*)loc = (int16_t) json_integer_value(val);
+            } else {
+                status = ERROR;
+                celix_err_pushf("Expected json integer type but got %i", json_typeof(val));
+            }
             break;
         case 'I' :
-            *(int32_t*)loc = (int32_t) json_integer_value(val);
+            if (json_is_integer(val)) {
+                *(int32_t*)loc = (int32_t) json_integer_value(val);
+            } else {
+                status = ERROR;
+                celix_err_pushf("Expected json integer type but got %i", json_typeof(val));
+            }
             break;
         case 'J' :
-            *(int64_t*)loc = (int64_t) json_integer_value(val);
+            if (json_is_integer(val)) {
+                *(int64_t*)loc = (int64_t) json_integer_value(val);
+            } else {
+                status = ERROR;
+                celix_err_pushf("Expected json integer type but got %i", json_typeof(val));
+            }
             break;
         case 'b' :
-            *(uint8_t*)loc = (uint8_t) json_integer_value(val);
+            if (json_is_integer(val)) {
+                *(uint8_t*)loc = (uint8_t) json_integer_value(val);
+            } else {
+                status = ERROR;
+                celix_err_pushf("Expected json integer type but got %i", json_typeof(val));
+            }
             break;
         case 's' :
-            *(uint16_t*)loc = (uint16_t) json_integer_value(val);
+            if (json_is_integer(val)) {
+                *(uint16_t*)loc = (uint16_t) json_integer_value(val);
+            } else {
+                status = ERROR;
+                celix_err_pushf("Expected json integer type but got %i", json_typeof(val));
+            }
             break;
         case 'i' :
-            *(uint32_t*)loc = (uint32_t) json_integer_value(val);
+            if (json_is_integer(val)) {
+                *(uint32_t*)loc = (uint32_t) json_integer_value(val);
+            } else {
+                status = ERROR;
+                celix_err_pushf("Expected json integer type but got %i", json_typeof(val));
+            }
             break;
         case 'j' :
-            *(uint64_t*)loc = (uint64_t) json_integer_value(val);
+            if (json_is_integer(val)) {
+                *(uint64_t*)loc = (uint64_t) json_integer_value(val);
+            } else {
+                status = ERROR;
+                celix_err_pushf("Expected json integer type but got %i", json_typeof(val));
+            }
             break;
         case 'E' :
             if (json_is_string(val)){
diff --git a/libs/etcdlib/src/etcd.c b/libs/etcdlib/src/etcd.c
index 37d1e4295..a4b806f65 100644
--- a/libs/etcdlib/src/etcd.c
+++ b/libs/etcdlib/src/etcd.c
@@ -252,7 +252,7 @@ etcd_get_recursive_values(json_t *js_root, etcdlib_key_value_callback callback,
 
 static long long etcd_get_current_index(const char *headerData) {
     long long index = -1;
-    char *indexStr = strstr(headerData, ETCD_HEADER_INDEX);
+    const char *indexStr = strstr(headerData, ETCD_HEADER_INDEX);
     indexStr += strlen(ETCD_HEADER_INDEX);
 
     if (sscanf(indexStr, "%lld\n", &index) == 1) {