Open zlr3538 opened 6 years ago
这个功能现在确实还不支持。你有没有比较好的办法呢?
我这几天绞尽脑汁,勉励改出了一个可以支持的样子,但是却完全失去了原有的样子,不仅有了start和end,而且参数的数量和位置也不再统一。 我觉得你这个封装的设计目的应该是,希望用简洁的格式,描述struct和json之间的转换关系。这也是为什么你的封装看起来不像是过程而像是一种声明。 我想到的一个办法,就是用一些声明语句,构造一个树来描述struct,那么这个如果这树和json解析的树相同,就可以用遍历的方法将他们两者进行转化。这样应该能保持简洁的描述,也可以处理json中各种情况,一次描述应该就可以实现两个方向的互转。毕竟C没有元信息,结构体和其中变量的描述,肯定要通过额外的方法再声明一遍。你看这个思路是不是可行?
树的方案是可行的,就是工作量会非常大。
start 和 end 的那个方案改完是什么样子?
大概是这样,可以说非常丑陋了,而且弄得很复杂,感觉也不是很靠谱
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;
}
可以把 s2j_struct_get_struct_element_start 与 s2j_struct_get_array_element_start ,以及对应的 end 合并为一个吗?
例如:s2j_struct_get_struct_array_element_start
我把他们拆成两个纯粹无奈之举,展开来其实是一个循环,在循环里面遍历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() \
} \
}
以下的这个结构体数组,能否转化为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];
参考下面的分支,已经实现结构体和数组的转换,并提供自动生成转换代码的脚本:) https://github.com/yuxuebao/struct2json
已经实现,自动生成的转换代码示例:
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;
cJSON struct_to_json_McBaseOrdrT(void struct_obj) { s2j_create_json_obj(jsonobj); McBaseOrdrT structobj = (McBaseOrdrT )struct_obj; s2j_json_set_basic_element(jsonobj, structobj, int, ordrNo); s2j_json_set_basic_element(jsonobj, structobj, int, intrlOrdrNo); s2j_json_set_basic_element(jsonobj, structobj, int, exePrc); s2j_json_set_basic_element(jsonobj, structobj, int, elstcPrc); s2j_json_set_basic_element(jsonobj, structobj, int, ordrQty); s2j_json_set_basic_element(jsonobj, structobj, int, effectTime); s2j_json_set_basic_element(jsonobj, structobj, int, ordSide); s2j_json_set_basic_element(jsonobj, structobj, int, ordrType); s2j_json_set_basic_element(jsonobj, structobj, int, usrSqno); s2j_json_set_basic_element(jsonobj, structobj, int, prdctSqno); s2j_json_set_basic_element(jsonobj, structobj, int, orgSqno); s2j_json_set_basic_element(jsonobj, structobj, int, extOrdType); s2j_json_set_basic_element(jsonobj, structobj, int, ordrRestr); return jsonobj; }
void json_to_struct_McBaseOrdrT(cJSON json_obj) { s2j_create_struct_obj(structobj, McBaseOrdrT); s2j_struct_get_basic_element(structobj,json_obj, int, ordrNo); s2j_struct_get_basic_element(structobj,json_obj, int, intrlOrdrNo); s2j_struct_get_basic_element(structobj,json_obj, int, exePrc); s2j_struct_get_basic_element(structobj,json_obj, int, elstcPrc); s2j_struct_get_basic_element(structobj,json_obj, int, ordrQty); s2j_struct_get_basic_element(structobj,json_obj, int, effectTime); s2j_struct_get_basic_element(structobj,json_obj, int, ordSide); s2j_struct_get_basic_element(structobj,json_obj, int, ordrType); s2j_struct_get_basic_element(structobj,json_obj, int, usrSqno); s2j_struct_get_basic_element(structobj,json_obj, int, prdctSqno); s2j_struct_get_basic_element(structobj,json_obj, int, orgSqno); s2j_struct_get_basic_element(structobj,json_obj, int, extOrdType); s2j_struct_get_basic_element(structobj,json_obj, int, ordrRestr); return structobj; }
typedef struct McBaseOrdrArray { McBaseOrdrT mcBaseOrdrArray[2] ; } McBaseOrdrArrayT;
cJSON struct_to_json_McBaseOrdrArrayT(void struct_obj) { s2j_create_json_obj(jsonobj); McBaseOrdrArrayT structobj = (McBaseOrdrArrayT )struct_obj; s2j_json_set_struct_array_element_by_func(jsonobj, structobj, McBaseOrdrT,mcBaseOrdrArray,2); return jsonobj; }
void json_to_struct_McBaseOrdrArrayT(cJSON json_obj) { s2j_create_struct_obj(structobj, McBaseOrdrArrayT); s2j_struct_get_struct_array_element_by_func(structobj, json_obj, McBaseOrdrT,mcBaseOrdrArray); return structobj; }
参考下面的分支,已经实现结构体和数组的转换,并提供自动生成转换代码的脚本:) https://github.com/yuxuebao/struct2json
Cool
如题,目前数组序列化只能是基本类型吗?如果数组里面是结构体这样的嵌套有没有解决办法