Last active
January 12, 2026 04:50
-
-
Save magicoal-nerb/619fcbc3def1c23edf2b1fedac29ea0d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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