Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

结构体数组如何序列化? #8

Open
zlr3538 opened this issue Aug 25, 2018 · 10 comments
Open

结构体数组如何序列化? #8

zlr3538 opened this issue Aug 25, 2018 · 10 comments

Comments

@zlr3538
Copy link

zlr3538 commented Aug 25, 2018

如题,目前数组序列化只能是基本类型吗?如果数组里面是结构体这样的嵌套有没有解决办法

@armink
Copy link
Owner

armink commented Aug 25, 2018

这个功能现在确实还不支持。你有没有比较好的办法呢?

@zlr3538
Copy link
Author

zlr3538 commented Aug 29, 2018

我这几天绞尽脑汁,勉励改出了一个可以支持的样子,但是却完全失去了原有的样子,不仅有了start和end,而且参数的数量和位置也不再统一。
我觉得你这个封装的设计目的应该是,希望用简洁的格式,描述struct和json之间的转换关系。这也是为什么你的封装看起来不像是过程而像是一种声明。
我想到的一个办法,就是用一些声明语句,构造一个树来描述struct,那么这个如果这树和json解析的树相同,就可以用遍历的方法将他们两者进行转化。这样应该能保持简洁的描述,也可以处理json中各种情况,一次描述应该就可以实现两个方向的互转。毕竟C没有元信息,结构体和其中变量的描述,肯定要通过额外的方法再声明一遍。你看这个思路是不是可行?

@armink
Copy link
Owner

armink commented Aug 29, 2018

树的方案是可行的,就是工作量会非常大。

start 和 end 的那个方案改完是什么样子?

@zlr3538
Copy link
Author

zlr3538 commented Aug 30, 2018

大概是这样,可以说非常丑陋了,而且弄得很复杂,感觉也不是很靠谱

typedef struct {
    char name[16];
} Hometown;

typedef struct {
    int ranking;
    int score;
} Results;

typedef struct {
    int id;
    double weight;
    char name[10];
    int attendance [10];
    Hometown hometown;
    Results results[5];
} Student;

/**
 * Student JSON object to structure object
 *
 * @param json_obj JSON object
 *
 * @return structure object
 */
static void *json_to_struct(json_object* json_obj) {
    /* create Student structure object */
    s2j_create_struct_obj(struct_student, Student);

    /* deserialize data to Student structure object. */
    s2j_struct_get_basic_element(struct_student, json_obj, int, id);
    s2j_struct_get_basic_element(struct_student, json_obj, double, weight);
    s2j_struct_get_basic_element(struct_student, json_obj, string, name);
    

    {
        s2j_struct_get_struct_element_start(struct_student, json_obj, int, attendance);
        s2j_struct_get_array_element_start(CHILD_STRUCT,CHILD_ELEMENT,int);
        s2j_struct_get_array_basic_element(ARRAY_STRUCT, ARRAY_ELEMENT, int, attendance);
        s2j_struct_get_array_element_end();
        s2j_struct_get_struct_element_end();
    }
    
    {
    /* deserialize data to Student.Hometown structure object. */
        s2j_struct_get_struct_element_start(struct_student, json_obj, Hometown, hometown);
        s2j_struct_get_basic_element(CHILD_STRUCT, CHILD_ELEMENT, string, name);
        s2j_struct_get_struct_element_end();
    }

    {
        s2j_struct_get_struct_element_start(struct_student, json_obj, Results, results);
        s2j_struct_get_array_element_start(CHILD_STRUCT,CHILD_ELEMENT,Results);        
        s2j_struct_get_basic_element(ARRAY_STRUCT, ARRAY_ELEMENT, int ,ranking);
        s2j_struct_get_basic_element(ARRAY_STRUCT, ARRAY_ELEMENT, int ,score);
        s2j_struct_get_array_element_end();
        s2j_struct_get_struct_element_end();
    }
    
    /* return Student structure object pointer */
    return struct_student;
}

/**
 * Student structure object to JSON object
 *
 * @param struct_obj structure object
 *
 * @param JSON object
 */
static json_object *struct_to_json(void* struct_obj) {
    Student *struct_student = (Student *)struct_obj;

    /* create Student JSON object */
    s2j_create_json_obj(json_student);

    /* serialize data to Student JSON object. */
    s2j_json_set_basic_element(json_student, struct_student, int, id);
    s2j_json_set_basic_element(json_student, struct_student, double, weight);
    s2j_json_set_basic_element(json_student, struct_student, string, name);

    {
        s2j_json_set_array_element_start(json_student, int, 10);
        s2j_json_set_array_basic_element(ARRAY_ELEMENT, struct_student, int, attendance);
        s2j_json_set_array_element_end(json_student, attendance);
    }

    {
        /* serialize data to Student.Hometown JSON object. */
        s2j_json_set_struct_element_start(struct_student, Hometown, hometown);
        s2j_json_set_basic_element(CHILD_ELEMENT, CHILD_STRUCT, string, name);
        s2j_json_set_struct_element_end(json_student, hometown);
    }

    {
        s2j_json_set_array_element_start(json_student, Results, 5);
        s2j_json_set_array_struct_element_start(struct_student, Results, results);
        s2j_json_set_basic_element(CHILD_ELEMENT, CHILD_STRUCT, int, ranking);
        s2j_json_set_basic_element(CHILD_ELEMENT, CHILD_STRUCT, int, score);
        s2j_json_set_struct_element_end(ARRAY_ELEMENT, results);
        s2j_json_set_array_element_end(json_student, results);
    }
    /* return Student JSON object pointer */
    return json_student;
}

@armink
Copy link
Owner

armink commented Aug 30, 2018

可以把 s2j_struct_get_struct_element_start 与 s2j_struct_get_array_element_start ,以及对应的 end 合并为一个吗?

例如:s2j_struct_get_struct_array_element_start

@zlr3538
Copy link
Author

zlr3538 commented Aug 30, 2018

我把他们拆成两个纯粹无奈之举,展开来其实是一个循环,在循环里面遍历struct
展开是下面这个样子,我这个因为需要把cjson换成json-c,其他一样的

#define S2J_STRUCT_GET_ARRAY_ELEMENT_START(to_struct, from_json, type) \
    { \
        struct json_object *array, *array_element; \
        size_t index = 0, size = 0; \
        array = from_json; \
        if (array) { \
            size = json_object_array_length(array); \
            while (index < size) { \
                array_element = json_object_array_get_idx(array, index); \
                if (array_element) { \
                    type *array_struct = &(((type*)(to_struct))[index]);
                    

#define S2J_STRUCT_GET_ARRAY_ELEMENT_END() \
                index++; } \
            } \
        } \
     }

#define S2J_STRUCT_GET_STRUCT_ELEMENT_START(to_struct, from_json, type, _element) \
    { \
        type *child_struct = &((to_struct)->_element); \
        struct json_object *child_element = json_object_object_get(from_json, #_element); \
        if(child_element) {

#define S2J_STRUCT_GET_STRUCT_ELEMENT_END() \
        } \
    }

@EveryDayNew
Copy link

以下的这个结构体数组,能否转化为json,如果能那种方法比较合适
typedef struct KR {
char name[50];
char evaluation[400];
float weight;
char completion[20];
float score;
} kr;

typedef struct objective {
char name[50];
kr KRs[3];
float score;
} obj;

typedef struct OKR {
char name[50];
float totalPoints;
float weight[2];
obj objs[2];
} okr;

okr okrs[12];

@yuxuebao
Copy link
Contributor

参考下面的分支,已经实现结构体和数组的转换,并提供自动生成转换代码的脚本:)
https://github.com/yuxuebao/struct2json

@yuxuebao
Copy link
Contributor

已经实现,自动生成的转换代码示例:
#if 0
typedef struct McBaseOrdrS
{
int64 ordrNo;
int64 intrlOrdrNo;
int64 exePrc;
int64 elstcPrc;
int64 ordrQty;
int64 effectTime;
int32 ordSide;
int32 ordrType;
int32 usrSqno;
int32 prdctSqno;
int32 orgSqno;
int32 extOrdType;
int32 ordrRestr;
} McBaseOrdrT, *pMcBaseOrdrT;
#endif
cJSON struct_to_json_McBaseOrdrT(void struct_obj)
{
s2j_create_json_obj(json_obj_);
McBaseOrdrT *struct_obj_ = (McBaseOrdrT *)struct_obj;
s2j_json_set_basic_element(json_obj_, struct_obj_, int, ordrNo);
s2j_json_set_basic_element(json_obj_, struct_obj_, int, intrlOrdrNo);
s2j_json_set_basic_element(json_obj_, struct_obj_, int, exePrc);
s2j_json_set_basic_element(json_obj_, struct_obj_, int, elstcPrc);
s2j_json_set_basic_element(json_obj_, struct_obj_, int, ordrQty);
s2j_json_set_basic_element(json_obj_, struct_obj_, int, effectTime);
s2j_json_set_basic_element(json_obj_, struct_obj_, int, ordSide);
s2j_json_set_basic_element(json_obj_, struct_obj_, int, ordrType);
s2j_json_set_basic_element(json_obj_, struct_obj_, int, usrSqno);
s2j_json_set_basic_element(json_obj_, struct_obj_, int, prdctSqno);
s2j_json_set_basic_element(json_obj_, struct_obj_, int, orgSqno);
s2j_json_set_basic_element(json_obj_, struct_obj_, int, extOrdType);
s2j_json_set_basic_element(json_obj_, struct_obj_, int, ordrRestr);
return json_obj_;
}

void json_to_struct_McBaseOrdrT(cJSON json_obj)
{
s2j_create_struct_obj(struct_obj_, McBaseOrdrT);
s2j_struct_get_basic_element(struct_obj_,json_obj, int, ordrNo);
s2j_struct_get_basic_element(struct_obj_,json_obj, int, intrlOrdrNo);
s2j_struct_get_basic_element(struct_obj_,json_obj, int, exePrc);
s2j_struct_get_basic_element(struct_obj_,json_obj, int, elstcPrc);
s2j_struct_get_basic_element(struct_obj_,json_obj, int, ordrQty);
s2j_struct_get_basic_element(struct_obj_,json_obj, int, effectTime);
s2j_struct_get_basic_element(struct_obj_,json_obj, int, ordSide);
s2j_struct_get_basic_element(struct_obj_,json_obj, int, ordrType);
s2j_struct_get_basic_element(struct_obj_,json_obj, int, usrSqno);
s2j_struct_get_basic_element(struct_obj_,json_obj, int, prdctSqno);
s2j_struct_get_basic_element(struct_obj_,json_obj, int, orgSqno);
s2j_struct_get_basic_element(struct_obj_,json_obj, int, extOrdType);
s2j_struct_get_basic_element(struct_obj_,json_obj, int, ordrRestr);
return struct_obj_;
}

#if 0
typedef struct McBaseOrdrArray
{
McBaseOrdrT mcBaseOrdrArray[2] ;
} McBaseOrdrArrayT;
#endif
cJSON struct_to_json_McBaseOrdrArrayT(void struct_obj)
{
s2j_create_json_obj(json_obj_);
McBaseOrdrArrayT *struct_obj_ = (McBaseOrdrArrayT *)struct_obj;
s2j_json_set_struct_array_element_by_func(json_obj_, struct_obj_, McBaseOrdrT,mcBaseOrdrArray,2);
return json_obj_;
}

void json_to_struct_McBaseOrdrArrayT(cJSON json_obj)
{
s2j_create_struct_obj(struct_obj_, McBaseOrdrArrayT);
s2j_struct_get_struct_array_element_by_func(struct_obj_, json_obj, McBaseOrdrT,mcBaseOrdrArray);
return struct_obj_;
}

@armink
Copy link
Owner

armink commented Feb 20, 2021

参考下面的分支,已经实现结构体和数组的转换,并提供自动生成转换代码的脚本:)
https://github.com/yuxuebao/struct2json

Cool

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants