dbutils/json.c

Fri, 12 Dec 2025 10:42:53 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Fri, 12 Dec 2025 10:42:53 +0100
changeset 30
d33eaaec15da
parent 29
b8c826c720f3
permissions
-rw-r--r--

update ucx

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2025 Olaf Wintermann. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "json.h"

CxJsonValue* dbuObjectToJson(DBUClass *type, void *obj, const CxAllocator *a) {
    return dbuObjectToJson2(type, obj, a, false, false);
}

CxJsonValue* dbuObjectToJson2(DBUClass *type, void *obj, const CxAllocator *a, bool setNull, bool forceString) {
    if(obj == NULL) {
        return cxJsonCreateLiteral(a, CX_JSON_NULL);
    }
    if(!a) {
        a = cxDefaultAllocator;
    }
    
    CxJsonValue *value = cxJsonCreateObj(a);
    if(!value) {
        return NULL;
    }
    
    // add all primitive values
    CxMapIterator i = cxMapIteratorValues(type->fields);
        for(int n=0;n<2;n++) {
            cx_foreach(DBUField *, field, i) {
            CxJsonValue *child = NULL;
            if(field->toBool) {
                bool b = field->toBool(field, obj);
                child = cxJsonCreateLiteral(a, b ? CX_JSON_TRUE : CX_JSON_FALSE);
            } else if(field->toInt64) {
                int64_t i = field->toInt64(field, obj);
                child = cxJsonCreateInteger(a, i);
            } else if(field->toUInt64) {
                uint64_t u = field->toUInt64(field, obj);
                child = cxJsonCreateInteger(a, (int64_t)u);
            } else if(field->toDouble) {
                double d = field->toDouble(field, obj);
                child = cxJsonCreateNumber(a, d);
            } else if(field->toString) {
                cxmutstr s = field->toString(field, obj, a);
                if(s.ptr) {
                    // we don't want to copy the string again, therefore
                    // we can't use cxJsonCreateString
                    child = cxMalloc(a, sizeof(CxJsonValue));
                    if(!child) {
                        cxFree(a, s.ptr);
                        return NULL;
                    }
                    child->allocator = a;
                    child->type = CX_JSON_STRING;
                    child->string = s;
                }
            } else if(field->toBinary) {
                // TODO
            } else if(field->toObject) {
                DBUObject child_obj = field->toObject(field, obj);
                if(child_obj == NULL) {
                    child = CX_JSON_NULL;
                } else if(field->objType) {
                    child = dbuObjectToJson2(field->objType, child_obj, a, setNull, forceString);
                }
            } else if(field->toList) {
                DBUAbstractList *list = field->toList(field, obj);
                child = cxJsonCreateArr(a);
                if(child) {
                    if(list->iterator) {
                        CxIterator iter = list->iterator(list);
                        cx_foreach(void *, elm, iter) {
                            DBUField *f = list->elementField(list, elm);
                            if(f->toObject) {
                                DBUObject child_obj = f->toObject(field, elm);
                                if(f->objType) {
                                    CxJsonValue *array_elm = dbuObjectToJson2(f->objType, child_obj, a, setNull, forceString);
                                    cxJsonArrAddValues(child, &array_elm, 1);
                                }
                            }
                        }
                    }
                }
            } else {
                continue; // non-serializable field
            }

            if(!child) {
                cxJsonValueFree(value);
                return NULL;
            }

            if(cxJsonObjPut(value, field->name, child)) {
                cxJsonValueFree(child);
                cxJsonValueFree(value);
                return NULL;
            }
        }
        i = cxMapIteratorValues(type->obj_fields);
    }
    
    return value;
}

mercurial