Skip to content

Instantly share code, notes, and snippets.

@magicoal-nerb
Last active January 12, 2026 04:50
Show Gist options
  • Select an option

  • Save magicoal-nerb/619fcbc3def1c23edf2b1fedac29ea0d to your computer and use it in GitHub Desktop.

Select an option

Save magicoal-nerb/619fcbc3def1c23edf2b1fedac29ea0d to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
public class JsonVariant {
// Referent
public JsonObject referent = null;
// Floating point number
public float number;
// String object
public string str;
// Constructors
public JsonVariant(JsonObject referent_) { referent = referent_; }
public JsonVariant(float number_) { number = number_; }
public JsonVariant(string str_) { str = str_; }
// Implicit casts
public static implicit operator JsonObject(JsonVariant variant) { return variant.referent; }
public static implicit operator string(JsonVariant variant) { return variant.str; }
public static implicit operator float(JsonVariant variant) { return variant.number; }
};
public class JsonObject {
// Dictionary of the JSON object
public Dictionary<string, JsonVariant> props = null;
// List of the JSON object
public List<JsonVariant> list = null;
// List of the JSON object
public int parent = 0;
};
// Our JSON parser assumes that the input
// is already valid. If it isn't, then this
// will give undefined behavior.
public class Json {
// Current node
public List<JsonObject> nodes;
// Cursor
private int cursor = 0;
// Current node
private int node = 0;
// Length
private int length;
// Character array
private char[] content;
// Main string
private string data;
public Json(string content_) {
JsonObject root = new JsonObject();
root.list = new List<JsonVariant>();
nodes = new List<JsonObject>();
nodes.Add(root);
content = content_.ToCharArray();
length = content.Length;
data = content_;
parse();
}
private JsonVariant parseOpenParenthesis() {
// Create a new object inside of our current
// node, and then assign it I guess?
JsonObject newNode;
int id = nodes.Count;
if(content[cursor] == '{') {
newNode = new JsonObject();
newNode.props = new Dictionary<string, JsonVariant>();
} else {
newNode = new JsonObject();
newNode.list = new List<JsonVariant>();
}
newNode.parent = node;
nodes.Add(newNode);
cursor++;
node = id;
return new JsonVariant(newNode);
}
private JsonVariant parseString() {
// Parses the string
cursor++;
int left = cursor;
while(content[cursor] != '"') {
cursor++;
}
cursor++;
return new JsonVariant(data.Substring(left, cursor - left - 1));
}
private JsonVariant parseNumber() {
int start = cursor;
while(
Char.IsDigit(content[cursor])
|| content[cursor] == '.'
|| content[cursor] == '-'
) {
cursor++;
}
return new JsonVariant(float.Parse(data.Substring(start, cursor - start)));
}
private void parseClosingParenthesis() {
// Backtracks up the parent
node = nodes[node].parent;
cursor++;
}
private void skipWhitespace() {
// Skips through whitespace
while(cursor < length && Char.IsWhiteSpace(content[cursor])) {
cursor++;
}
}
private void addElement(JsonObject current, ref string index, JsonVariant what) {
if(current.list != null) {
// Add to the current list
current.list.Add(what);
} else if(index != null) {
// Add to the property dictionary
current.props[index] = what;
index = null;
} else if(what.str != null) {
// We only set the index if the object
// is a string
index = what.str;
}
}
private void parse() {
// Our parser actually doesn't care
// about the : or , characters, we just assume the context
// provided by the list or dictionary constructors
string index = null;
while(cursor < length) {
skipWhitespace();
// Check for a digit
char chr = content[cursor];
if(Char.IsDigit(chr) || chr == '-') {
// Number
addElement(nodes[node], ref index, parseNumber());
} else if(chr == '{' || chr == '[') {
// Set property
addElement(nodes[node], ref index, parseOpenParenthesis());
} else if(chr == '}' || chr == ']') {
// Closing parenthesis
parseClosingParenthesis();
} else if(chr == '"') {
// We got a string!
addElement(nodes[node], ref index, parseString());
} else {
cursor++;
}
}
}
public JsonObject getRoot() {
return nodes[1];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment