implement primitive json to obj deserialization

Sat, 03 Jan 2026 18:19:58 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 03 Jan 2026 18:19:58 +0100
changeset 41
daabc9bb5445
parent 40
0b6bc15d022e
child 42
3c989bc611c6

implement primitive json to obj deserialization

dbutils/dbutils/json.h file | annotate | diff | comparison | revisions
dbutils/json.c file | annotate | diff | comparison | revisions
test/json.c file | annotate | diff | comparison | revisions
test/json.h file | annotate | diff | comparison | revisions
test/main.c file | annotate | diff | comparison | revisions
--- a/dbutils/dbutils/json.h	Sat Jan 03 17:21:52 2026 +0100
+++ b/dbutils/dbutils/json.h	Sat Jan 03 18:19:58 2026 +0100
@@ -47,6 +47,8 @@
 
 CxJsonValue* dbuObjectToJson2(DBUClass *type, void *obj, const CxAllocator *a, bool setNull, bool forceString);
 
+void* dbuJsonToObject(DBUClass *type, const CxAllocator *a, CxJsonValue *value);
+
 
 #ifdef __cplusplus
 }
--- a/dbutils/json.c	Sat Jan 03 17:21:52 2026 +0100
+++ b/dbutils/json.c	Sat Jan 03 18:19:58 2026 +0100
@@ -26,8 +26,12 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <stdio.h>
+
 #include "json.h"
 
+/* ---------------- Obj to JSON serialization functions ---------------------*/
+
 CxJsonValue* dbuObjectToJson(DBUClass *type, void *obj, const CxAllocator *a) {
     return dbuObjectToJson2(type, obj, a, false, false);
 }
@@ -123,3 +127,97 @@
     
     return value;
 }
+
+
+/* --------------- Json to Obj deserialization functions --------------------*/
+
+void* dbuJsonToObject(DBUClass *type, const CxAllocator *a, CxJsonValue *value) {
+    if(!cxJsonIsObject(value)) {
+        return NULL;
+    }
+    if(!a) {
+        a = cxDefaultAllocator;
+    }
+    
+    void *obj = cxMalloc(a, type->obj_size);
+    if(obj) {
+        memset(obj, 0, type->obj_size);
+    }
+    
+    char buf[64];
+    int len = 0;
+    
+    CxMapIterator i = cxMapIterator(value->object);
+    cx_foreach(CxMapEntry *, entry, i) {
+        DBUField *field = cxMapGet(type->fields, entry->key);
+        if(!field) {
+            continue;
+        }
+        
+        len = 0;
+        
+        CxJsonValue *child = entry->value;
+        switch(child->type) {
+            case CX_JSON_LITERAL: {
+                if(child->literal == CX_JSON_NULL) {
+                    if(field->initObjValue) {
+                        field->initObjValue(field, a, obj, NULL);
+                    }
+                    break;
+                } else {
+                    int b = child->literal == CX_JSON_TRUE;
+                    if(field->initIntValue) {
+                        field->initIntValue(field, a, obj, b);
+                        continue;
+                    } else {
+                        len = snprintf(buf, 64, "%d", b);
+                    }
+                }
+                break;
+            }
+            case CX_JSON_INTEGER: {
+                if(field->initIntValue) {
+                    field->initIntValue(field, a, obj, child->integer);
+                } else {
+                    len = snprintf(buf, 64, "%" PRId64, child->integer);
+                }
+                break;
+            }
+            case CX_JSON_NUMBER: {
+                if(field->initDoubleValue) {
+                    field->initDoubleValue(field, a, obj, child->number);
+                } else {
+                    len = snprintf(buf, 64, "%f", child->number);
+                }
+                break;
+            }
+            case CX_JSON_STRING: {
+                cxmutstr str = child->string;
+                if(field->initValue(field, a, obj, str.ptr, str.length)) {
+                    free(obj); // TODO: improve obj cleanup
+                    return NULL;
+                }
+                break;
+            }
+            case CX_JSON_OBJECT: {
+                // TODO
+                break;
+            }
+            case CX_JSON_ARRAY: {
+                // TODO
+                break;
+            }
+            default: break;
+        }
+        
+        if(len > 0) {
+            if(field->initValue(field, a, obj, buf, len)) {
+                // TODO: completely cleanup obj
+                free(obj);
+                return NULL;
+            }
+        }
+    }
+    
+    return obj;
+}
--- a/test/json.c	Sat Jan 03 17:21:52 2026 +0100
+++ b/test/json.c	Sat Jan 03 18:19:58 2026 +0100
@@ -315,3 +315,46 @@
         cxJsonValueFree(value);
     }
 }
+
+CX_TEST(testJsonToSimpleObject) {
+    const char *jsonStr =
+        "{"
+        "\"str\":\"hello\","
+        "\"str2\":\"world\","
+        "\"i8\":-12,"
+        "\"u8\":250,"
+        "\"i64\":-1234567890123,"
+        "\"i16\":-32000,"
+        "\"i32\":-2000000000,"
+        "\"u32\":4000000000,"
+        "\"u16\":65000,"
+        "\"u64\":123456789123456789,"
+        "\"bt\":true,"
+        "\"bf\":false,"
+        "\"d\":3.141592653589793"
+        "}";
+    
+    CxJsonValue *json;
+    cxJsonFromString(NULL, jsonStr, &json);
+    
+    CX_TEST_DO {
+        Test1 *obj = dbuJsonToObject(test1_class, NULL, json);
+        
+        CX_TEST_ASSERT(obj);
+        CX_TEST_ASSERT(!cx_strcmp(obj->str, "hello"));
+        CX_TEST_ASSERT(!cx_strcmp(obj->str2, "world"));
+        CX_TEST_ASSERT(obj->i8 == -12);
+        CX_TEST_ASSERT(obj->u8 == 250);
+        CX_TEST_ASSERT(obj->i64 == -1234567890123);
+        CX_TEST_ASSERT(obj->i16 == -32000);
+        CX_TEST_ASSERT(obj->i32 == -2000000000);
+        CX_TEST_ASSERT(obj->u32 == 4000000000);
+        CX_TEST_ASSERT(obj->u16 == 65000);
+        CX_TEST_ASSERT(obj->u64 == 123456789123456789);
+        CX_TEST_ASSERT(obj->bt);
+        CX_TEST_ASSERT(!obj->bf);
+        CX_TEST_ASSERT(obj->d < 3.1416 && obj->d > 3.1415);
+        
+        free(obj);
+    }
+}
--- a/test/json.h	Sat Jan 03 17:21:52 2026 +0100
+++ b/test/json.h	Sat Jan 03 18:19:58 2026 +0100
@@ -44,6 +44,8 @@
 CX_TEST(testObjectToJsonChildObj);
 CX_TEST(testObjectToJsonChildList);
 
+CX_TEST(testJsonToSimpleObject);
+
 
 #ifdef __cplusplus
 }
--- a/test/main.c	Sat Jan 03 17:21:52 2026 +0100
+++ b/test/main.c	Sat Jan 03 18:19:58 2026 +0100
@@ -144,6 +144,7 @@
     cx_test_register(suite, testObjectToJsonSimple);
     cx_test_register(suite, testObjectToJsonChildObj);
     cx_test_register(suite, testObjectToJsonChildList);
+    cx_test_register(suite, testJsonToSimpleObject);
     
     cx_test_run_stdout(suite);
     

mercurial