// 如果添加失败 返回 NULL // 如果添加成功,返回所添加的 json_object_t 结构指针 json_object_t * json_append(json_object_t * obj, const char * key, size_t key_len, json_type_t value_type, void * value, size_t value_len) { assert(obj); assert( (obj->object_type == JSON_OBJECT && key) || (obj->object_type != JSON_OBJECT) ); while( obj->value_type != JSON_NONE ) { if( !obj->next ) { if( obj->object_type == JSON_OBJECT ) { obj->next = json_create_object(); } else if ( obj->object_type == JSON_ARRAY ) { obj->next = json_create_array(); } else { return NULL; } } if( obj->next ) { obj = obj->next; } else { return NULL; } } if( obj->object_type == JSON_OBJECT ) { #ifdef __x86_64__ assert( !(key_len >> 18) ); #elif __i386__ assert( !(key_len >> 8) ); #endif obj->key = (char *)key; obj->key_len = key_len; }
int main(void) { struct json *reply, *item1, *item2, *params; struct jrpc_client *client = &my_client; int ret = jrpc_client_init(client, HOST, PORT); if (ret != 0) { exit(ret); } item1 = json_create_object(); json_add_number_to_object(item1, "A", 3); json_add_number_to_object(item1, "B", 10); item2 = json_create_object(); json_add_number_to_object(item2, "A", 1); json_add_number_to_object(item2, "B", 2); params = json_create_array(); json_add_item_to_object(item1,"S", item2); json_add_item_to_array(params, item1); // jrpc_client_call will free params if ((ret = jrpc_client_call(client, "foo", params, &reply)) != 0) { exit(ret); } printf("%s\n", json_to_string(reply)); json_delete(reply); jrpc_client_close(client); return 0; }
struct json *json_create_string_array(const char **strings, int count) { int i; struct json *n = 0, *p = 0, *a = json_create_array(); for (i = 0; a && i < count; i++) { n = json_create_string(strings[i]); if (!i) a->child = n; else suffix_object(p, n); p = n; } return a; }
struct json *json_create_double_array(double *numbers, int count) { int i; struct json *n = 0, *p = 0, *a = json_create_array(); for (i = 0; a && i < count; i++) { n = json_create_number(numbers[i]); if (!i) a->child = n; else suffix_object(p, n); p = n; } return a; }
static struct json *foo(struct jrpc_context * ctx, struct json *params, struct json *id) { struct json *reply, *item, *array; int a, b, i; char buf[1024]; json_dump(params); json_dump(id); item = json_get_object_item(params->child, "A"); a = item->valueint; item = json_get_object_item(params->child, "B"); b = item->valueint; sprintf(buf, "recv a:%d b:%d", a, b); array = json_create_array(); for(i = 0; i < a; i ++){ item = json_create_object(); json_add_number_to_object(item, "A", i); json_add_number_to_object(item, "B", b++); json_add_item_to_array(array, item); } reply = json_create_object(); json_add_item_to_object(reply, "Args", array); json_add_string_to_object(reply, "Str", buf); json_dump(reply); return reply; }
int json_parse_array( json_task_t *task, json_object_t *parent ) { char ch; json_object_t node, * append = NULL; node.next = parent; node.key = NULL; node.key_len = 0; if( !task->callback ) { if( !task->root ) { append = task->root = json_create_array(); } else { append = parent->value.p = json_create_array(); } } task->status = STS_ARRAY_START; while(( ch = *(task->str + task->count) )) { task->count ++; if( ch == ' ' || ch == '\n' || ch == '\t' ) { continue; } switch( task->status ) { case STS_ARRAY_START: if( ch == ']' ) { return 0; } else { /* 这里需要将计数减一,因为 json_parse_value 需要根据这一个字符判断 value 类型 */ task->count --; node.value.s = task->str + task->count; if( json_parse_value( task, &node ) != 0 ) { if( node.value_type == JSON_OBJECT || node.value_type == JSON_ARRAY ) { json_delete_object(node.value.p); } return -1; } // WARNING: value_len 可能发生溢出 node.value_len = task->str + task->count - node.value.s; // 对 value 进行处理 switch(node.value_type) { case JSON_STRING: // 去除字符串两端的引号 node.value.s += 1; node.value_len -= 2; break; case JSON_DOUBLE: // TODO 在解析测试用例时,atof 与 atoll 使解析时间延长了几乎一半 // 移除对数值的默认解析可以显著提升性能 node.value.d = atof(node.value.s); break; case JSON_LONGLONG: node.value.l = atoll(node.value.s); break; case JSON_ARRAY: case JSON_OBJECT: break; } // 需要放在 node.key_len ++ 之前以便正确输出数组下标 if( task->callback ) { task->callback( task, &node ); } if( !task->callback ) { switch( node.value_type ) { case JSON_ARRAY: case JSON_OBJECT: case JSON_STRING: append = json_append(append, node.key, node.key_len, node.value_type, node.value.p, node.value_len); break; default: append = json_append(append, node.key, node.key_len, node.value_type, &node.value, node.value_len); } } node.key_len ++; task->status = STS_ARRAY_COMMA; } break; case STS_ARRAY_COMMA: if( ch == ',' ) { task->status = STS_ARRAY_START; } else if( ch == ']' ) { return 0; } else { task->err_msg = "expect ',' or ']'"; return -1; } break; default: task->err_msg = "unknown status"; return -1; } } task->err_msg = "unexpect EOF"; return -1; }