diff --git a/include/neuron/json/json.h b/include/neuron/json/json.h index 0e55ce767..96f090911 100644 --- a/include/neuron/json/json.h +++ b/include/neuron/json/json.h @@ -147,10 +147,13 @@ typedef struct neu_json_elem { union neu_json_value v; uint8_t precision; double bias; + bool ok; } neu_json_elem_t; #define NEU_JSON_ELEM_SIZE(elems) sizeof(elems) / sizeof(neu_json_elem_t) +void neu_json_elem_free(neu_json_elem_t *elem); + /* New a empty josn array */ void *neu_json_array(); diff --git a/include/neuron/msg.h b/include/neuron/msg.h index f4613f1bd..aff263cc9 100644 --- a/include/neuron/msg.h +++ b/include/neuron/msg.h @@ -887,8 +887,6 @@ static inline void neu_trans_data_free(neu_reqresp_trans_data_t *data) { if (tag_value->value.type == NEU_TYPE_PTR) { free(tag_value->value.value.ptr.ptr); - } else if (tag_value->value.type == NEU_TYPE_CUSTOM) { - json_decref(tag_value->value.value.json); } } utarray_free(data->tags); diff --git a/plugins/mqtt/mqtt_handle.c b/plugins/mqtt/mqtt_handle.c index b0bcf1f52..14d995657 100644 --- a/plugins/mqtt/mqtt_handle.c +++ b/plugins/mqtt/mqtt_handle.c @@ -277,6 +277,10 @@ static int json_value_to_tag_value(union neu_json_value *req, value->value.i64s.i64s[i] = req->val_array_int64.i64s[i]; } break; + case NEU_JSON_OBJECT: + value->type = NEU_TYPE_CUSTOM; + value->value.json = req->val_object; + break; default: return -1; } diff --git a/plugins/restful/rw_handle.c b/plugins/restful/rw_handle.c index 855874998..89c8b60ed 100644 --- a/plugins/restful/rw_handle.c +++ b/plugins/restful/rw_handle.c @@ -363,6 +363,10 @@ void handle_write(nng_aio *aio) req->value.val_array_bool.bools[i]; } break; + case NEU_JSON_OBJECT: + cmd.value.type = NEU_TYPE_CUSTOM; + cmd.value.value.json = req->value.val_object; + break; default: assert(false); break; @@ -560,6 +564,11 @@ void handle_write_tags(nng_aio *aio) req->tags[i].value.val_array_bool.bools[k]; } break; + case NEU_JSON_OBJECT: + cmd.tags[i].value.type = NEU_TYPE_CUSTOM; + cmd.tags[i].value.value.json = + req->tags[i].value.val_object; + break; default: assert(false); break; diff --git a/src/adapter/driver/driver.c b/src/adapter/driver/driver.c index 900dfe435..ca26a4260 100644 --- a/src/adapter/driver/driver.c +++ b/src/adapter/driver/driver.c @@ -751,6 +751,7 @@ static void fix_value(neu_datatag_t *tag, neu_type_e value_type, case NEU_TYPE_ARRAY_INT64: case NEU_TYPE_ARRAY_CHAR: case NEU_TYPE_ARRAY_BOOL: + case NEU_TYPE_CUSTOM: break; case NEU_TYPE_BIT: value->type = NEU_TYPE_BIT; diff --git a/src/parser/neu_json_rw.c b/src/parser/neu_json_rw.c index 223a656b0..897ebb3a2 100644 --- a/src/parser/neu_json_rw.c +++ b/src/parser/neu_json_rw.c @@ -355,6 +355,10 @@ int decode_write_req_json(void *json_obj, neu_json_write_req_t *req) req->t = req_elems[3].t; req->value = req_elems[3].v; + if (req->t == NEU_JSON_OBJECT) { + json_incref(req->value.val_object); + } + return ret; error: @@ -502,6 +506,10 @@ static int decode_write_tags_req_json(void * json_obj, req->tags[i].t = v_elems[1].t; req->tags[i].value = v_elems[1].v; + if (req->tags[i].t == NEU_JSON_OBJECT) { + json_incref(req->tags[i].value.val_object); + } + if (ret != 0) { for (; i >= 0; --i) { free(req->tags[i].tag); diff --git a/src/utils/json.c b/src/utils/json.c index 819a3e51c..b402ba8b6 100644 --- a/src/utils/json.c +++ b/src/utils/json.c @@ -64,6 +64,62 @@ static double format_tag_value(float ele_value) return value * negative; } +void neu_json_elem_free(neu_json_elem_t *elem) +{ + if (elem == NULL) { + return; + } + + switch (elem->t) { + case NEU_JSON_ARRAY_BOOL: + free(elem->v.val_array_bool.bools); + break; + case NEU_JSON_ARRAY_UINT8: + free(elem->v.val_array_uint8.u8s); + break; + case NEU_JSON_ARRAY_INT8: + free(elem->v.val_array_int8.i8s); + break; + case NEU_JSON_ARRAY_UINT16: + free(elem->v.val_array_uint16.u16s); + break; + case NEU_JSON_ARRAY_INT16: + free(elem->v.val_array_int16.i16s); + break; + case NEU_JSON_ARRAY_UINT32: + free(elem->v.val_array_uint32.u32s); + break; + case NEU_JSON_ARRAY_INT32: + free(elem->v.val_array_int32.i32s); + break; + case NEU_JSON_ARRAY_UINT64: + free(elem->v.val_array_uint64.u64s); + break; + case NEU_JSON_ARRAY_INT64: + free(elem->v.val_array_int64.i64s); + break; + case NEU_JSON_ARRAY_FLOAT: + free(elem->v.val_array_float.f32s); + break; + case NEU_JSON_ARRAY_DOUBLE: + free(elem->v.val_array_double.f64s); + break; + case NEU_JSON_ARRAY_STR: + for (int i = 0; i < elem->v.val_array_str.length; ++i) { + free(elem->v.val_array_str.p_strs[i]); + } + free(elem->v.val_array_str.p_strs); + break; + case NEU_JSON_OBJECT: + json_decref(elem->v.val_object); + break; + case NEU_JSON_STR: + free(elem->v.val_str); + break; + default: + break; + } +} static json_t *encode_object_value(neu_json_elem_t *ele) { json_t *ob = NULL; @@ -309,9 +365,13 @@ static int decode_object(json_t *root, neu_json_elem_t *ele) break; } } + } else if (json_is_object(ob)) { + ele->t = NEU_JSON_OBJECT; } } + ele->ok = true; + switch (ele->t) { case NEU_JSON_BIT: ele->v.val_bit = json_integer_value(ob); @@ -321,11 +381,13 @@ static int decode_object(json_t *root, neu_json_elem_t *ele) break; case NEU_JSON_STR: { if (!json_is_string(ob)) { + ele->ok = false; zlog_error(neuron, "json decode: %s failed", ele->name); return -1; } const char *str_val = json_string_value(ob); if (str_val == NULL) { + ele->ok = false; zlog_error(neuron, "json decode: %s failed", ele->name); return -1; } @@ -385,6 +447,160 @@ static int decode_object(json_t *root, neu_json_elem_t *ele) } break; } + case NEU_JSON_ARRAY_UINT8: { + json_t *value = NULL; + + ele->v.val_array_uint8.length = json_array_size(ob); + if (ele->v.val_array_uint8.length > 0) { + int index = 0; + + ele->v.val_array_uint8.u8s = + calloc(ele->v.val_array_uint8.length, sizeof(int8_t)); + json_array_foreach(ob, index, value) + { + if (json_is_real(value)) { + ele->v.val_array_uint8.u8s[index] = + (uint8_t) json_real_value(value); + } else { + ele->v.val_array_uint8.u8s[index] = + json_integer_value(value); + } + } + } + break; + } + case NEU_JSON_ARRAY_INT8: { + json_t *value = NULL; + + ele->v.val_array_int8.length = json_array_size(ob); + if (ele->v.val_array_int8.length > 0) { + int index = 0; + + ele->v.val_array_int8.i8s = + calloc(ele->v.val_array_int8.length, sizeof(int8_t)); + json_array_foreach(ob, index, value) + { + if (json_is_real(value)) { + ele->v.val_array_int8.i8s[index] = + (int8_t) json_real_value(value); + } else { + ele->v.val_array_int8.i8s[index] = + json_integer_value(value); + } + } + } + break; + } + case NEU_JSON_ARRAY_UINT16: { + json_t *value = NULL; + + ele->v.val_array_uint16.length = json_array_size(ob); + if (ele->v.val_array_uint16.length > 0) { + int index = 0; + + ele->v.val_array_uint16.u16s = + calloc(ele->v.val_array_uint16.length, sizeof(int16_t)); + json_array_foreach(ob, index, value) + { + if (json_is_real(value)) { + ele->v.val_array_uint16.u16s[index] = + (uint16_t) json_real_value(value); + } else { + ele->v.val_array_uint16.u16s[index] = + json_integer_value(value); + } + } + } + break; + } + case NEU_JSON_ARRAY_INT16: { + json_t *value = NULL; + + ele->v.val_array_int16.length = json_array_size(ob); + if (ele->v.val_array_int16.length > 0) { + int index = 0; + + ele->v.val_array_int16.i16s = + calloc(ele->v.val_array_int16.length, sizeof(int16_t)); + json_array_foreach(ob, index, value) + { + if (json_is_real(value)) { + ele->v.val_array_int16.i16s[index] = + (int16_t) json_real_value(value); + } else { + ele->v.val_array_int16.i16s[index] = + json_integer_value(value); + } + } + } + break; + } + case NEU_JSON_ARRAY_UINT32: { + json_t *value = NULL; + + ele->v.val_array_uint32.length = json_array_size(ob); + if (ele->v.val_array_uint32.length > 0) { + int index = 0; + + ele->v.val_array_uint32.u32s = + calloc(ele->v.val_array_uint32.length, sizeof(int32_t)); + json_array_foreach(ob, index, value) + { + if (json_is_real(value)) { + ele->v.val_array_uint32.u32s[index] = + (uint32_t) json_real_value(value); + } else { + ele->v.val_array_uint32.u32s[index] = + json_integer_value(value); + } + } + } + break; + } + case NEU_JSON_ARRAY_INT32: { + json_t *value = NULL; + + ele->v.val_array_int32.length = json_array_size(ob); + if (ele->v.val_array_int32.length > 0) { + int index = 0; + + ele->v.val_array_int32.i32s = + calloc(ele->v.val_array_int32.length, sizeof(int32_t)); + json_array_foreach(ob, index, value) + { + if (json_is_real(value)) { + ele->v.val_array_int32.i32s[index] = + (int32_t) json_real_value(value); + } else { + ele->v.val_array_int32.i32s[index] = + json_integer_value(value); + } + } + } + break; + } + case NEU_JSON_ARRAY_UINT64: { + json_t *value = NULL; + + ele->v.val_array_uint64.length = json_array_size(ob); + if (ele->v.val_array_uint64.length > 0) { + int index = 0; + + ele->v.val_array_uint64.u64s = + calloc(ele->v.val_array_uint64.length, sizeof(int64_t)); + json_array_foreach(ob, index, value) + { + if (json_is_real(value)) { + ele->v.val_array_uint64.u64s[index] = + (uint64_t) json_real_value(value); + } else { + ele->v.val_array_uint64.u64s[index] = + json_integer_value(value); + } + } + } + break; + } case NEU_JSON_ARRAY_INT64: { json_t *value = NULL; @@ -407,6 +623,27 @@ static int decode_object(json_t *root, neu_json_elem_t *ele) } break; } + case NEU_JSON_ARRAY_FLOAT: { + json_t *value = NULL; + + ele->v.val_array_float.length = json_array_size(ob); + if (ele->v.val_array_float.length > 0) { + int index = 0; + + ele->v.val_array_float.f32s = + calloc(ele->v.val_array_float.length, sizeof(float)); + json_array_foreach(ob, index, value) + { + if (json_is_integer(value)) { + ele->v.val_array_float.f32s[index] = + (float) json_integer_value(value); + } else { + ele->v.val_array_float.f32s[index] = json_real_value(value); + } + } + } + break; + } case NEU_JSON_ARRAY_DOUBLE: { json_t *value = NULL; @@ -433,6 +670,7 @@ static int decode_object(json_t *root, neu_json_elem_t *ele) ele->v.val_object = ob; break; default: + ele->ok = false; zlog_error(neuron, "json decode unknown type: %d", ele->t); return -1; } diff --git a/tests/ut/json_test.cc b/tests/ut/json_test.cc index c0e1b3089..aa64ca8e0 100644 --- a/tests/ut/json_test.cc +++ b/tests/ut/json_test.cc @@ -95,6 +95,90 @@ TEST(JsonTest, DecodeArray) EXPECT_EQ(789, tags[1].v.val_int); } +TEST(JsonTest, DecodeArray1) +{ + char *buf = + (char *) "{\"field1\": [1,2,3],\"field2\": [-1,0,1], \"field3\": [1.1, " + "2.1, -3.1], \"field4\": [true, false, true]}"; + neu_json_elem_t elems[11]; + elems[0].name = (char *) "field1"; + elems[0].t = NEU_JSON_ARRAY_UINT8; + elems[1].name = (char *) "field2"; + elems[1].t = NEU_JSON_ARRAY_INT8; + elems[2].name = (char *) "field1"; + elems[2].t = NEU_JSON_ARRAY_UINT16; + elems[3].name = (char *) "field2"; + elems[3].t = NEU_JSON_ARRAY_INT16; + elems[4].name = (char *) "field1"; + elems[4].t = NEU_JSON_ARRAY_UINT32; + elems[5].name = (char *) "field2"; + elems[5].t = NEU_JSON_ARRAY_INT32; + elems[6].name = (char *) "field1"; + elems[6].t = NEU_JSON_ARRAY_UINT64; + elems[7].name = (char *) "field2"; + elems[7].t = NEU_JSON_ARRAY_INT64; + + elems[8].name = (char *) "field3"; + elems[8].t = NEU_JSON_ARRAY_FLOAT; + elems[9].name = (char *) "field3"; + elems[9].t = NEU_JSON_ARRAY_DOUBLE; + elems[10].name = (char *) "field4"; + elems[10].t = NEU_JSON_ARRAY_BOOL; + + EXPECT_EQ(11, sizeof(elems) / sizeof(neu_json_elem_t)); + EXPECT_EQ(11, NEU_JSON_ELEM_SIZE(elems)); + EXPECT_EQ(0, neu_json_decode(buf, NEU_JSON_ELEM_SIZE(elems), elems)); + + EXPECT_EQ(1, elems[0].v.val_array_uint8.u8s[0]); + EXPECT_EQ(2, elems[0].v.val_array_uint8.u8s[1]); + EXPECT_EQ(3, elems[0].v.val_array_uint8.u8s[2]); + + EXPECT_EQ(-1, elems[1].v.val_array_int8.i8s[0]); + EXPECT_EQ(0, elems[1].v.val_array_int8.i8s[1]); + EXPECT_EQ(1, elems[1].v.val_array_int8.i8s[2]); + + EXPECT_EQ(1, elems[2].v.val_array_uint16.u16s[0]); + EXPECT_EQ(2, elems[2].v.val_array_uint16.u16s[1]); + EXPECT_EQ(3, elems[2].v.val_array_uint16.u16s[2]); + + EXPECT_EQ(-1, elems[3].v.val_array_int16.i16s[0]); + EXPECT_EQ(0, elems[3].v.val_array_int16.i16s[1]); + EXPECT_EQ(1, elems[3].v.val_array_int16.i16s[2]); + + EXPECT_EQ(1, elems[4].v.val_array_uint32.u32s[0]); + EXPECT_EQ(2, elems[4].v.val_array_uint32.u32s[1]); + EXPECT_EQ(3, elems[4].v.val_array_uint32.u32s[2]); + + EXPECT_EQ(-1, elems[5].v.val_array_int32.i32s[0]); + EXPECT_EQ(0, elems[5].v.val_array_int32.i32s[1]); + EXPECT_EQ(1, elems[5].v.val_array_int32.i32s[2]); + + EXPECT_EQ(1, elems[6].v.val_array_uint64.u64s[0]); + EXPECT_EQ(2, elems[6].v.val_array_uint64.u64s[1]); + EXPECT_EQ(3, elems[6].v.val_array_uint64.u64s[2]); + + EXPECT_EQ(-1, elems[7].v.val_array_int64.i64s[0]); + EXPECT_EQ(0, elems[7].v.val_array_int64.i64s[1]); + EXPECT_EQ(1, elems[7].v.val_array_int64.i64s[2]); + + EXPECT_FLOAT_EQ(1.1, elems[8].v.val_array_float.f32s[0]); + EXPECT_FLOAT_EQ(2.1, elems[8].v.val_array_float.f32s[1]); + EXPECT_FLOAT_EQ(-3.1, elems[8].v.val_array_float.f32s[2]); + + EXPECT_DOUBLE_EQ(1.1, elems[9].v.val_array_double.f64s[0]); + EXPECT_DOUBLE_EQ(2.1, elems[9].v.val_array_double.f64s[1]); + EXPECT_DOUBLE_EQ(-3.1, elems[9].v.val_array_double.f64s[2]); + + EXPECT_EQ(true, elems[10].v.val_array_bool.bools[0]); + EXPECT_EQ(false, elems[10].v.val_array_bool.bools[1]); + EXPECT_EQ(true, elems[10].v.val_array_bool.bools[2]); + + for (size_t i = 0; i < NEU_JSON_ELEM_SIZE(elems); i++) { + /* code */ + neu_json_elem_free(&elems[i]); + } +} + TEST(JsonTest, DecodeUndefine) { char *buf =