diff --git a/examples/example-04.c b/examples/example-04.c new file mode 100644 index 0000000..981d7bb --- /dev/null +++ b/examples/example-04.c @@ -0,0 +1,71 @@ + +#include +#include +#include +#include + +#include "tiny-json.h" +#include "../json-maker/json-maker.h" + +int main( void ) { + + printf("tiny-json objects to json...\n"); + { + // convert a static string to a tiny-json objects + const char* original = "{\"ts\":\"2023-02-09T23:18:27Z\",\"dev\":true,\"info\":{\"r1\":16807,\"ra\":[282475249,1622650073,984943658,1144108930],\"r2\":470211272},\"r3\":44}"; + char *data = malloc( strlen(original)+1 ); + strcpy(data, original); + + json_t pool[16] = {0,}; + json_t const *e = json_create( data, pool, sizeof(pool)/sizeof(pool[0]) ); + assert( e ); + + // test something in those tiny-json objects + json_t const *e1 = json_getProperty( e, "dev" ); + const char* key = json_getName(e1); + bool value = json_getBoolean(e1); + assert( strcmp( key, "dev" ) == 0 ); + assert( value == true ); + + // convert tiny-json objects back into json string + size_t sz = 2048; + char *json = calloc( 1, sz ); + assert(json); + + // just convert back, don't change anything + json_ObjectsToJSON( json, &sz, e ); + assert( strcmp( json, original ) == 0 ); + + // convert while replacing a key + json_replaceInteger( json, &sz, e, "r1", 22 ); + assert( strstr( json, "\"ts\":\"2023-02-09T23:18:27Z\"") ); // no change + assert( strstr( json, "\"r1\":22") ); // <- changed + assert( strstr( json, "\"dev\":true") ); // no change + + // retain last change by reseting json input & storing tiny-objects + strcpy(data, json); + e = json_create( data, pool, sizeof(pool)/sizeof(pool[0]) ); + + // convert while replacing a key + json_replaceBoolean( json, &sz, e, "dev", false ); + assert( strstr( json, "\"ts\":\"2023-02-09T23:18:27Z\"") ); // no change + assert( strstr( json, "\"r1\":22") ); // still changed + assert( strstr( json, "\"dev\":false") ); // <- changed + + // retain last change by reseting json input & storing tiny-objects + strcpy(data, json); + e = json_create( data, pool, sizeof(pool)/sizeof(pool[0]) ); + + // convert while replacing a key + json_replaceString( json, &sz, e, "ts", "ABCDEF" ); + assert( strstr( json, "\"ts\":\"ABCDEF\"") ); // <- changed + assert( strstr( json, "\"r1\":22") ); // still changed + assert( strstr( json, "\"dev\":false") ); // still changed + + free(data); + free(json); + } + printf("pass\n"); + return 0; +} + diff --git a/examples/makefile b/examples/makefile index 4a1f78e..9eb1ee1 100644 --- a/examples/makefile +++ b/examples/makefile @@ -1,6 +1,6 @@ CC = gcc -CFLAGS = -std=c99 -Wall -pedantic +CFLAGS = -std=c99 -Wall -pedantic -I. -I.. -I../../json-maker -DJSON_REVERSER src = $(wildcard *.c) src += $(wildcard ../*.c) @@ -9,7 +9,7 @@ dep = $(obj:.o=.d) .PHONY: build all clean -build: example-01.exe example-02.exe example-03.exe +build: example-01.exe example-02.exe example-03.exe example-04.exe all: clean build @@ -19,16 +19,19 @@ clean:: rm -rf *.exe -example-01.exe: example-01.o ../tiny-json.o +example-01.exe: example-01.o ../tiny-json.o ../../json-maker/json-maker.o gcc $(CFLAGS) -o $@ $^ -example-02.exe: example-02.o ../tiny-json.o +example-02.exe: example-02.o ../tiny-json.o ../../json-maker/json-maker.o gcc $(CFLAGS) -o $@ $^ -example-03.exe: example-03.o ../tiny-json.o - gcc $(CFLAGS) -o $@ $^ +example-03.exe: example-03.o ../tiny-json.o ../../json-maker/json-maker.o + gcc $(CFLAGS) -o $@ $^ + +example-04.exe: example-04.o ../tiny-json.o ../../json-maker/json-maker.o + gcc $(CFLAGS) -o $@ $^ -include $(dep) %.d: %.c - $(CC) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@ \ No newline at end of file + $(CC) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@ diff --git a/tiny-json.c b/tiny-json.c index 90dc160..2c583a6 100644 --- a/tiny-json.c +++ b/tiny-json.c @@ -465,3 +465,92 @@ static char* setToNull( char* ch ) { static bool isEndOfPrimitive( char ch ) { return ch == ',' || isOneOfThem( ch, blank ) || isOneOfThem( ch, endofblock ); } + + +#ifdef JSON_REVERSER + +#include +#include "json-maker.h" + +static char* objectToJSON(char* o, size_t* sz, const json_t* e, const char* property, const char* newString, const int newInteger) { + for( e = json_getChild(e); e!=0; e = json_getSibling(e) ) { + const char *key = json_getName(e); + switch( json_getType( e ) ) { + case JSON_OBJ: { + o = json_objOpen( o, key, sz ); + o = objectToJSON(o, sz, e, property, newString, newInteger); + o = json_objClose( o, sz ); + break; } + case JSON_TEXT: { + const char *value = json_getValue(e); + if ( key && property && !strcmp( key, property ) ) { + value = newString; + } + o = json_str( o, key, value, sz ); + break; } + case JSON_INTEGER: { + int value = json_getInteger(e); + if ( key && property && !strcmp( key, property ) ) { + value = newInteger; + } + o = json_int( o, key, value, sz ); + break; } + case JSON_ARRAY: { + o = json_arrOpen( o, key, sz); + o = objectToJSON(o, sz, e, property, newString, newInteger); + o = json_arrClose( o, sz ); + break; } + case JSON_BOOLEAN: { + bool value = json_getBoolean(e); + if ( key && property && !strcmp( key, property ) ) { + value = newInteger; + } + o = json_bool( o, key, value, sz ); + break; } + case JSON_REAL: + case JSON_NULL: + default: + assert(0); // not supported + break; + } + } + return o; +} + +char* json_ObjectsToJSON(char* json, size_t* sz, const json_t* e) { + char *o = json; + o = json_objOpen( o, NULL, sz ); + o = objectToJSON( o, sz, e, 0, 0, 0 ); + o = json_objClose( o, sz ); + o = json_end( o, sz ); + return json; +} + +char* json_replaceString(char* json, size_t* sz, const json_t* e, const char* key, const char* value) { + char *o = json; + o = json_objOpen( o, NULL, sz ); + o = objectToJSON( o, sz, e, key, value, 0 ); + o = json_objClose( o, sz ); + o = json_end( o, sz ); + return json; +} + +char* json_replaceInteger(char* json, size_t* sz, const json_t* e, const char* key, const int value) { + char *o = json; + o = json_objOpen( o, NULL, sz ); + o = objectToJSON( o, sz, e, key, 0, value ); + o = json_objClose( o, sz ); + o = json_end( o, sz ); + return json; +} + +char* json_replaceBoolean(char* json, size_t* sz, const json_t* e, const char* key, const int value) { + char *o = json; + o = json_objOpen( o, NULL, sz ); + o = objectToJSON( o, sz, e, key, 0, value ); + o = json_objClose( o, sz ); + o = json_end( o, sz ); + return json; +} + +#endif diff --git a/tiny-json.h b/tiny-json.h index 2b527e7..dbd5fde 100644 --- a/tiny-json.h +++ b/tiny-json.h @@ -167,6 +167,30 @@ struct jsonPool_s { * This property is always unnamed and its type is JSON_OBJ. */ json_t const* json_createWithPool( char* str, jsonPool_t* pool ); + +#ifdef JSON_REVERSER + +#include +#include "json-maker.h" + +/** reverse the action of json_createWithPool. + * i.e. convert all the json_t* tiny json objects back into a string + * caller must allocate json string large enough to thold the string and set sz accordingly. + * returns pointer to json string */ +char* json_ObjectsToJSON(char* json, size_t* sz, const json_t* e); + +/** json_ObjectsToJSON but also finds the property matching *key and replaces it with value. + * if caller intends on calling more than one property, then they should + * retain the change by reseting json input & storing tiny-objects via + strcpy(data, json); + e = json_create( data, pool, sizeof(pool)/sizeof(pool[0]) ); + and then calling the json_replace api again. */ +char* json_replaceString(char* json, size_t* sz, const json_t* e, const char* key, const char* value); +char* json_replaceInteger(char* json, size_t* sz, const json_t* e, const char* key, const int value); +char* json_replaceBoolean(char* json, size_t* sz, const json_t* e, const char* key, const int value); + +#endif + /** @ } */ #ifdef __cplusplus