2 // JSON data type and serializer for Citadel
4 // Copyright (c) 1987-2023 by the citadel.org team
6 // This program is open source software. Use, duplication, or disclosure
7 // is subject to the terms of the GNU General Public License, version 3.
10 #include <sys/types.h>
18 #include "libcitadel.h"
35 void DeleteJSONValue(void *vJsonValue) {
36 JsonValue *Val = (JsonValue*) vJsonValue;
37 FreeStrBuf(&Val->Name);
38 FreeStrBuf(&Val->Value);
39 DeleteHash(&Val->SubValues);
44 JsonValue *NewJsonObject(const char *Key, long keylen) {
47 Ret = (JsonValue*) malloc(sizeof(JsonValue));
48 memset(Ret, 0, sizeof(JsonValue));
49 Ret->Type = JSON_OBJECT;
51 Ret->Name = NewStrBufPlain(Key, keylen);
53 Ret->SubValues = NewHash(1, NULL);
58 JsonValue *NewJsonArray(const char *Key, long keylen) {
61 Ret = (JsonValue*) malloc(sizeof(JsonValue));
62 memset(Ret, 0, sizeof(JsonValue));
63 Ret->Type = JSON_ARRAY;
65 Ret->Name = NewStrBufPlain(Key, keylen);
67 Ret->SubValues = NewHash(1, lFlathash);
72 JsonValue *NewJsonNumber(const char *Key, long keylen, long Number) {
75 Ret = (JsonValue*) malloc(sizeof(JsonValue));
76 memset(Ret, 0, sizeof(JsonValue));
79 Ret->Name = NewStrBufPlain(Key, keylen);
81 Ret->Value = NewStrBufPlain(NULL, 64);
82 StrBufPrintf(Ret->Value, "%ld", Number);
87 JsonValue *NewJsonBigNumber(const char *Key, long keylen, double Number) {
90 Ret = (JsonValue*) malloc(sizeof(JsonValue));
91 memset(Ret, 0, sizeof(JsonValue));
94 Ret->Name = NewStrBufPlain(Key, keylen);
96 Ret->Value = NewStrBufPlain(NULL, 128);
97 StrBufPrintf(Ret->Value, "%f", Number);
102 JsonValue *NewJsonString(const char *Key, long keylen, StrBuf *CopyMe, int copy_or_smash) {
105 Ret = (JsonValue*) malloc(sizeof(JsonValue));
106 memset(Ret, 0, sizeof(JsonValue));
107 Ret->Type = JSON_STRING;
109 Ret->Name = NewStrBufPlain(Key, keylen);
111 if (copy_or_smash == NEWJSONSTRING_COPYBUF) {
112 Ret->Value = NewStrBufDup(CopyMe);
114 else if (copy_or_smash == NEWJSONSTRING_SMASHBUF) {
118 Ret->Value = NULL; // error condition
124 JsonValue *NewJsonPlainString(const char *Key, long keylen, const char *CopyMe, long len) {
127 Ret = (JsonValue*) malloc(sizeof(JsonValue));
128 memset(Ret, 0, sizeof(JsonValue));
129 Ret->Type = JSON_STRING;
131 Ret->Name = NewStrBufPlain(Key, keylen);
133 Ret->Value = NewStrBufPlain(CopyMe, len);
138 JsonValue *NewJsonNull(const char *Key, long keylen) {
141 Ret = (JsonValue*) malloc(sizeof(JsonValue));
142 memset(Ret, 0, sizeof(JsonValue));
143 Ret->Type = JSON_NULL;
145 Ret->Name = NewStrBufPlain(Key, keylen);
147 Ret->Value = NewStrBufPlain(HKEY("nulll"));
152 JsonValue *NewJsonBool(const char *Key, long keylen, int value) {
155 Ret = (JsonValue*) malloc(sizeof(JsonValue));
156 memset(Ret, 0, sizeof(JsonValue));
157 Ret->Type = JSON_BOOL;
159 Ret->Name = NewStrBufPlain(Key, keylen);
162 Ret->Value = NewStrBufPlain(HKEY("true"));
165 Ret->Value = NewStrBufPlain(HKEY("false"));
171 void JsonArrayAppend(JsonValue *Array, JsonValue *Val) {
173 if (Array->Type != JSON_ARRAY) {
177 n = GetCount(Array->SubValues);
178 Put(Array->SubValues, LKEY(n), Val, DeleteJSONValue);
182 void JsonObjectAppend(JsonValue *Array, JsonValue *Val) {
183 if ((Array->Type != JSON_OBJECT) || (Val->Name == NULL)) {
186 Put(Array->SubValues, SKEY(Val->Name), Val, DeleteJSONValue);
190 void SerializeJson(StrBuf *Target, JsonValue *Val, int FreeVal) {
191 void *vValue, *vPrevious;
199 StrBufAppendBufPlain(Target, HKEY("\""), 0);
201 char *plain = (char *)ChrPtr(Val->Value);
202 if (!IsEmptyStr(plain)) {
203 int len = strlen(plain);
204 for (i=0; i<len; ++i) {
205 // JSON escaped strings as per RFC 7159 section 7
206 if (plain[i] == '\r') {
207 StrBufAppendBufPlain(Target, HKEY("\\r"), 0);
209 else if (plain[i] == '\n') {
210 StrBufAppendBufPlain(Target, HKEY("\\n"), 0);
212 else if (plain[i] == '\"') {
213 StrBufAppendBufPlain(Target, HKEY("\\\""), 0);
215 else if (plain[i] == '\\') {
216 StrBufAppendBufPlain(Target, HKEY("\\\\"), 0);
218 else if (plain[i] < 32) {
219 StrBufAppendPrintf(Target, "\\u%04x", plain[i]);
222 StrBufAppendBufPlain(Target, &plain[i], 1, 0);
226 StrBufAppendBufPlain(Target, HKEY("\""), 0);
229 StrBufAppendBuf(Target, Val->Value, 0);
232 StrBufAppendBuf(Target, Val->Value, 0);
235 StrBufAppendBuf(Target, Val->Value, 0);
239 StrBufAppendBufPlain(Target, HKEY("["), 0);
240 It = GetNewHashPos(Val->SubValues, 0);
241 while (GetNextHashPos(Val->SubValues, It, &keylen, &Key, &vValue)) {
242 if (vPrevious != NULL) {
243 StrBufAppendBufPlain(Target, HKEY(","), 0);
245 SubVal = (JsonValue*) vValue;
246 SerializeJson(Target, SubVal, 0);
249 StrBufAppendBufPlain(Target, HKEY("]"), 0);
254 StrBufAppendBufPlain(Target, HKEY("{"), 0);
255 It = GetNewHashPos(Val->SubValues, 0);
256 while (GetNextHashPos(Val->SubValues, It, &keylen, &Key, &vValue)) {
257 SubVal = (JsonValue*) vValue;
259 if (vPrevious != NULL) {
260 StrBufAppendBufPlain(Target, HKEY(","), 0);
262 StrBufAppendBufPlain(Target, HKEY("\""), 0);
263 StrBufAppendBuf(Target, SubVal->Name, 0);
264 StrBufAppendBufPlain(Target, HKEY("\":"), 0);
266 SerializeJson(Target, SubVal, 0);
269 StrBufAppendBufPlain(Target, HKEY("}"), 0);
274 DeleteJSONValue(Val);