diff --git a/Changelog b/Changelog index 362d0a4..47e4b7b 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,7 @@ +2026-08-04: +- JSON handling with arrays had serval issues. + added test-json file to test also nested arrays. + 2026-08-02: - JSON to string reports wired to JSON_T_NONE types. also empty names? - we will ignore these. diff --git a/UDPTCPNetwork-json.h b/UDPTCPNetwork-json.h index 54a6a33..bdcf801 100644 --- a/UDPTCPNetwork-json.h +++ b/UDPTCPNetwork-json.h @@ -15,26 +15,30 @@ enum { }; class JSONElement { -public: - int type; - std::string name; - std::string value; + public: + int type; + std::string name; + std::string value; - JSONElement() { Clear(); }; - ~JSONElement() {}; + JSONElement() { Clear(); }; + ~JSONElement() {}; - void Clear() { type = JSON_T_NONE; name = ""; value = ""; }; - void Set (std::string n, double v); - void Set (std::string n, int v); - void Set (std::string n, int64_t v); - void Set (std::string n, std::string v); - void SetArray (std::string n, std::list *l); - void SetArray (std::string n); - void SetAddArray (std::string n, std::string jpstring); - void SetObject (std::string n, std::string s); - static std::string StringAddEscape(std::string *s); - static std::string StringRemoveEscape(std::string *s); - std::string GetString(); + void Clear() { type = JSON_T_NONE; name = ""; value = ""; }; + void Set (std::string n, double v); + void Set (std::string n, int v); + void Set (std::string n, int64_t v); + void Set (std::string n, std::string v); + void SetArray (std::string n, std::list *l); + void SetArray (std::string n); + void SetAddArrayEscaped (std::string n, std::string jpstring); + void SetAddArray (std::string n, std::string jpstring); + void SetAddArray (std::string n, double v); + void SetAddArray (std::string n, int v); + void SetAddArray (std::string n, int64_t v); + void SetObject (std::string n, std::string s); + static std::string StringAddEscape(std::string *s); + static std::string StringRemoveEscape(std::string *s); + std::string GetString(); }; class JSONParse { diff --git a/json.cc b/json.cc index 94f468d..acd5d60 100644 --- a/json.cc +++ b/json.cc @@ -270,29 +270,21 @@ int JSONParse::GetObject(std::string varname, JSONParse *dest) { #define MAXRECURSIVE 255 /// @brief Reads the source and returns the string of element requested. -/// @param src source json array +/// @param src source json array [ ...., .....] /// @param idx index to read /// @param dest destiantion of the string /// @return 0 not found else 1 int JSONParse::GetIdx(std::string src, int idx, std::string *dest) { char recursive[MAXRECURSIVE]; int i = 0, rcnt = 0, cnt = 0; - // debug ("src:%s\n\n", src.c_str()); (*dest) = ""; for (i = 0; i < MAXRECURSIVE; i++) recursive[i] = 0; for (i = 0; i < (int) src.length() && rcnt < MAXRECURSIVE && cnt <= idx; i++) { -/* if (src[i] == '[' || src[i] == ']' || src[i] == '"' || src[i] == ',' || src[i] == '}' || src[i] == '{') { - int _i; - debug ("src[i]:%c i:%d rcnt:%d cnt:%d idx:%d recursive:", src[i], i, rcnt, cnt, idx); - for (int _i = 0; _i < rcnt; _i++) printf ("%c", recursive[_i]); - printf ("\n"); - } -*/ if (src[i] == '[') { recursive[rcnt++] = src[i]; - continue; + if (rcnt == 1) continue; } else if (src[i] == '{' ) recursive[rcnt++] = src[i]; else if (src[i] == '}' && recursive[rcnt-1] == '{') rcnt--; @@ -303,9 +295,11 @@ int JSONParse::GetIdx(std::string src, int idx, std::string *dest) { continue; } else if (src[i] == ']' && rcnt > 0) { - continue; + rcnt--; + recursive[rcnt] = 0; + if (rcnt == 0) continue; } - + recursive[rcnt] = 0; if (rcnt > 0 && cnt == idx) { (*dest) += src[i]; if (src[i] == '\\') (*dest) += src[i]; @@ -324,14 +318,19 @@ int JSONParse::GetIdx(std::string src, int idx, std::string *dest) { } #undef MAXRECURSIVE + int JSONParse::GetValueIdx(std::string varname, int idx, std::string *dest) { std::list::iterator iter; - + std::string d; + int ret = 0; if (dest == NULL) return 0; for (iter = names.begin(); iter != names.end(); iter++) { if (varname.compare(iter->name) == 0) { - return GetIdx(iter->value, idx, dest); + ret = GetIdx(iter->value, idx, &d); + if (d[0]== '"') *dest = d.substr(1, d.length()-2); + else *dest = d; + return ret; } } @@ -557,7 +556,7 @@ void JSONElement::SetArray (std::string n, std::list *l) { }; -void JSONElement::SetAddArray (std::string n, std::string jpstring) { +void JSONElement::SetAddArrayEscaped (std::string n, std::string jpstring) { std::size_t ab; // start of array [ std::size_t ae; // end of array ] @@ -573,9 +572,35 @@ void JSONElement::SetAddArray (std::string n, std::string jpstring) { value = value.substr(0, ae); - if (value.length() > 2) value += ","; + if (value.length() > 1) value += ","; value += jpstring + "]"; -} +}; + + +void JSONElement::SetAddArray (std::string n, std::string v) { + std::string s; + s = "\"" + StringAddEscape(&v) + "\""; + SetAddArrayEscaped(n, s); +}; + + +void JSONElement::SetAddArray (std::string n, double v) { + std::string s = std::to_string(v); + SetAddArrayEscaped(n, s); +}; + + +void JSONElement::SetAddArray (std::string n, int v) { + std::string s = std::to_string(v); + SetAddArrayEscaped(n, s); +}; + + +void JSONElement::SetAddArray (std::string n, int64_t v) { + std::string s = std::to_string(v); + SetAddArrayEscaped(n, s); +}; + void JSONElement::SetObject (std::string n, std::string s) { diff --git a/test-json.cc b/test-json.cc index 971ad53..4c2cb5a 100644 --- a/test-json.cc +++ b/test-json.cc @@ -2,7 +2,8 @@ #include #include "UDPTCPNetwork.h" -int main(int argc, char** argv) { + +int test_json_basic() { JSONParse jpa; JSONParse jp; JSONElement je; @@ -17,7 +18,7 @@ int main(int argc, char** argv) { jpa.Clear(); jpa.AddObject("value_i", i); jpa.AddObject("value_2i", i*2); - je.SetAddArray("testarray", jpa.ToString()); + je.SetAddArrayEscaped("testarray", jpa.ToString()); } jp.AddObject(je); jp.GetValueString("somestring", &s); @@ -29,7 +30,103 @@ int main(int argc, char** argv) { jpa.GetValueInt("value_2i", &b); if (a *2 != b) r = 0; } - printf ("Test Array: %s\n", r ? (char*)"true" : (char*) "false"); + return r; +}; + + +// test embedded arrays, write and read from file. +int test_json_embedded() { + char* test_char[] = {"one", "two", "three", "four", "five", "six", NULL}; + JSONParse jp,jpdata; + JSONElement je, je1, je2; + std::string s = ""; + int j,i, r = 0; + + jp.Clear(); + je.Clear(); + for (i = 0; test_char[i] != NULL; i++) { + jpdata.Clear(); + jpdata.AddObject("name", test_char[i]); + jpdata.AddObject("index", i); + je1.Clear(); + for (int j = 0; j < 4; j++) { + je1.SetAddArray("intarray", j); + } + + je2.Clear(); + for (j = 0; test_char[j] != NULL; j++) { + je2.SetAddArray("stringarray", test_char[j]); + } + + jpdata.AddObject(je1); + jpdata.AddObject(je2); + je.SetAddArrayEscaped("testarray", jpdata.ToString()); + } + jp.AddObject(je); + jp.SaveToFile("test.json"); + + // reload from file + jp.Clear(); + je.Clear(); + je1.Clear(); + je2.Clear(); + jp.LoadFromFile("test.json"); + + for (r = 1, i = 0; test_char[i] != NULL; i++) { + jpdata.Clear(); + jp.GetObjectIdx("testarray", i, &jpdata); + jpdata.GetValueString("name", &s); + if (s.compare(test_char[i]) != 0) { + printf ("test_json_embedded: name mismatch: %s != %s\n", s.c_str(), test_char[i]); + r = 0; + } + + int idx = -1; + jpdata.GetValueInt("index", &idx); + if (idx != i) { + printf ("test_json_embedded: index mismatch: %d != %d\n", idx, i); + r = 0; + } + + // check intarray + for (j = 0; j < 4; j++) { + std::string v = ""; + jpdata.GetValueIdx("intarray", j, &v); + if (atoi (v.c_str()) != j) { + printf ("test_json_embedded: intarray mismatch: %s != %d\n", v.c_str(), j); + r = 0; + } + } + + // check stringarray + for (j = 0; test_char[j] != NULL; j++) { + jpdata.GetValueIdx("stringarray", j, &s); + if (s.compare(test_char[j]) != 0) { + printf ("test_json_embedded: stringarray mismatch: %s != %s\n", s.c_str(), test_char[j]); + r = 0; + } + } + } + + + // delete testfile + remove("test.json"); + + return r; +}; + + +int main(int argc, char** argv) { + int ret = 0; + int res = 0; - return 0; + if ((ret = test_json_basic()) == 0) res = 1; + printf ("test_json_basic: %s\n", ret ? "PASSED" : "FAILED"); + + if ((ret = test_json_embedded()) == 0) res = 1; + printf ("test_json_embedded: %s\n", ret ? "PASSED" : "FAILED"); + + return res; }; + +