Skip to content

Commit 07bf982

Browse files
committed
Implemented a utility function to convert JSON values to strings.
1 parent c99dda7 commit 07bf982

File tree

2 files changed

+119
-2
lines changed

2 files changed

+119
-2
lines changed

include/jtk/support/json.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,6 @@ jtk_JsonValue_t* jtk_JsonValue_forTrue();
6464
jtk_JsonValue_t* jtk_JsonValue_forFalse();
6565

6666
jtk_JsonValue_t* jtk_parseJson(const uint8_t* sequence, int32_t size, jtk_JsonError_t* error);
67-
uint8_t* jtk_toJson(jtk_JsonValue_t* value, int32_t* size);
67+
uint8_t* jtk_toJson(jtk_JsonValue_t* value, int32_t* size, bool pretty);
6868

6969
#endif /* JTK_SUPPORT_JSON_H */

source/jtk/support/json.c

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,11 @@ static Token* createToken(Parser* parser);
230230
static void onNewLine(Parser* parser);
231231
static void decimalIntegerLiteral(Parser* parser);
232232

233+
static void indent(jtk_StringBuilder_t* builder, int32_t depth);
234+
static void toString(jtk_StringBuilder_t* builder, jtk_JsonValue_t* value);
235+
static void toPrettyString(jtk_StringBuilder_t* builder, jtk_JsonValue_t* value, int32_t depth, bool member);
236+
237+
233238
Parser* newParser(const uint8_t* input, int32_t inputSize) {
234239
/* The constructor invokes consume() to initialize
235240
* the LA(1) character. Therefore, we assign negative values
@@ -822,4 +827,116 @@ jtk_JsonValue_t* jtk_JsonValue_forTrue() {
822827

823828
void handleError() {
824829
printf("Errro!\n");
825-
}
830+
}
831+
832+
void indent(jtk_StringBuilder_t* builder, int32_t depth) {
833+
jtk_StringBuilder_multiply_z(builder, " ", 4, depth);
834+
}
835+
836+
void toString(jtk_StringBuilder_t* builder, jtk_JsonValue_t* value) {
837+
if (value->type == JTK_JSON_VALUE_OBJECT) {
838+
jtk_StringBuilder_appendCodePoint(builder, '{');
839+
jtk_Iterator_t* iterator = jtk_HashMap_getEntryIterator(value->object);
840+
bool first = true;
841+
while (jtk_Iterator_hasNext(iterator)) {
842+
jtk_HashMapEntry_t* entry = (jtk_HashMapEntry_t*)jtk_Iterator_getNext(iterator);
843+
844+
if (!first) {
845+
jtk_StringBuilder_appendCodePoint(builder, ',');
846+
}
847+
848+
jtk_StringBuilder_appendCodePoint(builder, '"');
849+
jtk_StringBuilder_append_z(builder, (char*)entry->m_key);
850+
jtk_StringBuilder_appendCodePoint(builder, ':');
851+
toString(builder, (jtk_JsonValue_t*)entry->m_value);
852+
853+
first = false;
854+
}
855+
jtk_StringBuilder_appendCodePoint(builder, '}');
856+
}
857+
else if (value->type == JTK_JSON_VALUE_ARRAY) {
858+
jtk_StringBuilder_appendCodePoint(builder, '[');
859+
int32_t limit = jtk_ArrayList_getSize(value->array);
860+
int32_t i;
861+
for (i = 0; i < limit; i++) {
862+
jtk_JsonValue_t* element = (jtk_JsonValue_t*)jtk_ArrayList_getValue(value->array, i);
863+
toString(builder, element);
864+
865+
if (i + 1 < limit) {
866+
jtk_StringBuilder_appendCodePoint(builder, ',');
867+
}
868+
}
869+
jtk_StringBuilder_appendCodePoint(builder, ']');
870+
}
871+
else if (value->type == JTK_JSON_VALUE_STRING) {
872+
jtk_StringBuilder_appendCodePoint(builder, '"');
873+
jtk_StringBuilder_appendEx_z(builder, value->string.bytes, value->string.length);
874+
jtk_StringBuilder_appendCodePoint(builder, '"');
875+
}
876+
}
877+
878+
void toPrettyString(jtk_StringBuilder_t* builder, jtk_JsonValue_t* value,
879+
int32_t depth, bool member) {
880+
if (value->type == JTK_JSON_VALUE_OBJECT) {
881+
jtk_StringBuilder_appendEx_z(builder, "{\n", 2);
882+
jtk_Iterator_t* iterator = jtk_HashMap_getEntryIterator(value->object);
883+
bool first = true;
884+
while (jtk_Iterator_hasNext(iterator)) {
885+
jtk_HashMapEntry_t* entry = (jtk_HashMapEntry_t*)jtk_Iterator_getNext(iterator);
886+
887+
if (!first) {
888+
jtk_StringBuilder_appendEx_z(builder, ",\n", 2);
889+
}
890+
891+
indent(builder, depth + 1);
892+
jtk_StringBuilder_appendCodePoint(builder, '"');
893+
jtk_StringBuilder_append_z(builder, (char*)entry->m_key);
894+
jtk_StringBuilder_appendEx_z(builder, "\": ", 3);
895+
toPrettyString(builder, (jtk_JsonValue_t*)entry->m_value, depth + 1, true);
896+
897+
first = false;
898+
}
899+
jtk_StringBuilder_appendCodePoint(builder, '\n');
900+
indent(builder, depth);
901+
jtk_StringBuilder_appendCodePoint(builder, '}');
902+
}
903+
else if (value->type == JTK_JSON_VALUE_ARRAY) {
904+
jtk_StringBuilder_appendEx_z(builder, "[\n", 2);
905+
int32_t limit = jtk_ArrayList_getSize(value->array);
906+
int32_t i;
907+
for (i = 0; i < limit; i++) {
908+
jtk_JsonValue_t* element = (jtk_JsonValue_t*)jtk_ArrayList_getValue(value->array, i);
909+
indent(builder, depth + 1);
910+
toPrettyString(builder, element, depth + 1, true);
911+
912+
if (i + 1 < limit) {
913+
jtk_StringBuilder_appendCodePoint(builder, ',');
914+
}
915+
jtk_StringBuilder_appendCodePoint(builder, '\n');
916+
}
917+
indent(builder, depth);
918+
jtk_StringBuilder_appendCodePoint(builder, ']');
919+
}
920+
else if (value->type == JTK_JSON_VALUE_STRING) {
921+
jtk_StringBuilder_appendCodePoint(builder, '"');
922+
jtk_StringBuilder_appendEx_z(builder, (char*)value->string.bytes, value->string.length);
923+
jtk_StringBuilder_appendCodePoint(builder, '"');
924+
}
925+
926+
if (!member) {
927+
jtk_StringBuilder_appendCodePoint(builder, '\n');
928+
}
929+
}
930+
931+
uint8_t* jtk_toJson(jtk_JsonValue_t* value, int32_t* size, bool pretty) {
932+
jtk_StringBuilder_t* builder = jtk_StringBuilder_new();
933+
if (pretty) {
934+
toPrettyString(builder, value, 0, false);
935+
}
936+
else {
937+
toString(builder, value);
938+
}
939+
uint8_t* result = jtk_StringBuilder_toCString(builder, size);
940+
jtk_StringBuilder_delete(builder);
941+
return result;
942+
}

0 commit comments

Comments
 (0)