Sat, 03 Jan 2026 18:19:58 +0100
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);