Skip to content

Instantly share code, notes, and snippets.

@opsJson
Last active May 2, 2024 18:24
Show Gist options
  • Save opsJson/d79503f7b206c6697f20d8c979e3e74a to your computer and use it in GitHub Desktop.
Save opsJson/d79503f7b206c6697f20d8c979e3e74a to your computer and use it in GitHub Desktop.
Simple JSON parser in C. Parse until find the values you want. Allocate just the values you want.
#ifndef _JSON_PARSER_H_
#define _JSON_PARSER_H_
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifndef JSON_ALLOC
#define JSON_ALLOC malloc
#endif
char *json_get(const char *json, const char *key) {
unsigned int i, size, key_size;
int start = 0, end = 0;
const char *_key = NULL;
if (json == NULL) return NULL;
if (key == NULL) return NULL;
size = strlen(json);
key_size = strlen(key);
for (i=0; i<size; i++) {
char c = json[i];
if (c == '\"') {
start = i + 1;
for (i=i+1; i<size; i++) {
c = json[i];
if (c == '\"' && json[i-1] != '\\') break;
}
_key = json + start;
}
else if (c == ':') {
for (i=i+1; i<size; i++) {
c = json[i];
if (c == '\"') {
start = i + 1;
for (i=i+1; i<size; i++) {
c = json[i];
if (c == '\"' && json[i-1] != '\\') break;
}
end = i - start;
break;
}
else if (c == '[') {
int braces = 0;
int brackets = 0;
char instring = 0;
start = i;
for (i=i+1; i<size; i++) {
c = json[i];
if (c == '\"' && json[i-1] != '\\') instring = !instring;
if (instring) continue;
if (c == '[') brackets++;
else if (c == ']') brackets--;
else if (c == '{') braces++;
else if (c == '}') braces--;
if (braces > 0) continue;
if (brackets > 0) continue;
if (brackets < 0) break;
}
end = i - start + 1;
break;
}
else if (c == '{') {
int braces = 0;
int brackets = 0;
char instring = 0;
start = i;
for (i=i+1; i<size; i++) {
c = json[i];
if (c == '\"' && json[i-1] != '\\') instring = !instring;
if (instring) continue;
if (c == '[') brackets++;
else if (c == ']') brackets--;
else if (c == '{') braces++;
else if (c == '}') braces--;
if (braces > 0) continue;
if (brackets > 0) continue;
if (braces < 0) break;
}
end = i - start + 1;
break;
}
else if (!isspace(c)) {
start = i;
for (i=i+1; i<size; i++) {
c = json[i];
if (isspace(c)) break;
if (c == ',') break;
if (c == '}') break;
}
end = i - start;
break;
}
}
if (_key && strncmp(_key, key, key_size) == 0) {
char *value = JSON_ALLOC(end + 1);
if (value == NULL) return NULL;
strncpy(value, json + start, end);
value[end] = '\0';
return value;
}
}
}
return NULL;
}
int array_length(const char *array) {
unsigned int i, size, count;
int brackets, braces;
char instring;
if (array == NULL) return -1;
size = strlen(array);
count = 0;
braces = 0;
brackets = -1;
instring = 0;
for (i=0; i<size; i++) {
char c = array[i];
if (count == 0 && c != '[' && c != ']' && !isspace(c)) count++;
if (c == '\"' && array[i-1] != '\\') instring = !instring;
if (instring) continue;
if (c == '[') brackets++;
else if (c == ']') brackets--;
else if (c == '{') braces++;
else if (c == '}') braces--;
if (brackets > 0) continue;
if (braces > 0) continue;
if (c == ',') count++;
}
return count;
}
char *array_get(const char *array, unsigned int index) {
unsigned int i, size, count;
int start = 0, end = 0;
char *value;
if (array == NULL) return NULL;
size = strlen(array);
count = 0;
for (i=0; i<size; i++) {
char c = array[i];
if (c == '[') break;
}
for (i=i+1; i<size; i++) {
char c = array[i];
if (c == '\"') {
start = i + 1;
for (i=i+1; i<size; i++) {
c = array[i];
if (c == '\"' && array[i-1] != '\\') break;
}
end = i - start;
if (count == index) break;
count++;
}
else if (c == '[') {
int braces = 0;
int brackets = 0;
char instring = 0;
start = i;
for (i=i+1; i<size; i++) {
c = array[i];
if (c == '\"' && array[i-1] != '\\') instring = !instring;
if (instring) continue;
if (c == '[') brackets++;
else if (c == ']') brackets--;
else if (c == '{') braces++;
else if (c == '}') braces--;
if (brackets < 0) break;
}
end = i - start + 1;
if (count == index) break;
count++;
}
else if (c == '{') {
int braces = 0;
int brackets = 0;
char instring = 0;
start = i;
for (i=i+1; i<size; i++) {
c = array[i];
if (c == '\"' && array[i-1] != '\\') instring = !instring;
if (instring) continue;
if (c == '[') brackets++;
else if (c == ']') brackets--;
else if (c == '{') braces++;
else if (c == '}') braces--;
if (braces < 0) break;
}
end = i - start + 1;
if (count == index) break;
count++;
}
else if (c != ',' && c != ']' && !isspace(c)) {
start = i;
for (i=i+1; i<size; i++) {
c = array[i];
if (c == ']') break;
if (c == ',') break;
if (isspace(c)) break;
}
end = i - start;
if (count == index) break;
count++;
}
}
if (i == size) count--;
if (index != count) return NULL;
value = JSON_ALLOC(end + 1);
if (value == NULL) return NULL;
strncpy(value, array + start, end);
value[end] = '\0';
return value;
}
#endif
/*///////////////////////////////////
Testing:
///////////////////////////////////*/
#include <stdio.h>
int main(void) {
const char *jsonString = "{"
" \"name\": \"John Doe\","
" \"age\": 25,"
" \"height\": 1.75,"
" \"single\": true,"
" \"colors\": [\"red\", \"green\", \"blue\"],"
" \"address\": {"
" \"street\": \"123 Main St\","
" \"city\": \"Example City\","
" \"state\": \"EX\""
" },"
" \"friends\": ["
" {\"name\": \"Friend 1\", \"age\": 28},"
" {\"name\": \"Friend 2\", \"age\": 30}"
" ]"
"}";
char *name = json_get(jsonString, "name");
char *age = json_get(jsonString, "age");
char *height = json_get(jsonString, "height");
char *single = json_get(jsonString, "single");
char *colors = json_get(jsonString, "colors");
char *address = json_get(jsonString, "address");
char *friends = json_get(jsonString, "friends");
printf("name => %s\n", name);
printf("age => %i\n", atoi(age));
printf("height => %.2f\n", atof(height));
printf("single => %s\n", single);
printf("colors => %s\n", colors);
printf("address => %s\n", address);
printf("friends => %s\n", friends);
printf("\n");
int i, size;
size = array_length(colors);
for (i = 0; i < size; i++) {
char *color = array_get(colors, i);
printf("colors[%i] = %s\n", i, color);
free(color);
}
printf("\n");
char *street = json_get(address, "street");
char *city = json_get(address, "city");
char *state = json_get(address, "state");
printf("street => %s\n", street);
printf("city => %s\n", city);
printf("state => %s\n", state);
printf("\n");
size = array_length(friends);
for (i = 0; i < size; i++) {
char *friend = array_get(friends, i);
char *friendName = json_get(friend, "name");
char *friendAge = json_get(friend, "age");
printf("friends[%i].name = %s\n", i, friendName);
printf("friends[%i].age = %i\n", i, atoi(friendAge));
free(friend);
free(friendName);
free(friendAge);
}
free(name);
free(age);
free(height);
free(single);
free(colors);
free(address);
free(friends);
free(street);
free(city);
free(state);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment