Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@rendon
Last active February 18, 2018 04:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rendon/c1639842844ef4439944c314bd7684b7 to your computer and use it in GitHub Desktop.
Save rendon/c1639842844ef4439944c314bd7684b7 to your computer and use it in GitHub Desktop.
Basic JSON parser (super incomplete)
package mx.letmethink;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
String text = "{}";
// System.out.println(new JsonParser(text).parse());
// System.out.println(new JsonParser("{\"key\": \"value\", \"num\": 1234}").parse());
System.out.println(new JsonParser("{\"key\":{\"a\":{\"b\":\"{12345}678\"}}}").parse());
}
}
class JsonParser {
private static final char CLOSING_BRACE = '}';
private static final char COMMA = ',';
private final char[] chars;
int position;
private static final JsonException UNEXPECTED_END_OF_TEXT = new JsonException("Unexpected end of text");
public JsonParser(String text) {
this.chars = text.toCharArray();
}
public JsonObject parse() {
return readObject();
}
public JsonObject readObject() {
JsonObject object = new JsonObject();
readOpeningBrace();
while (true) {
if (peek() == CLOSING_BRACE) {
break;
}
String key = readKey();
readColon();
if (Character.isDigit(peek())) {
JsonNumber jsonNumber = readNumber();
object.put(key, jsonNumber);
} else if (peek() == '"') {
object.put(key, readString());
} else {
object.put(key, readObject());
}
if (peek() == CLOSING_BRACE) {
break;
}
readComma();
}
readClosingBrace();
return object;
}
private JsonNumber readNumber() {
strip();
long value = 0;
while (position < chars.length && Character.isDigit(chars[position])) {
value = value * 10 + chars[position++] - '0';
}
if (position == chars.length) {
throw UNEXPECTED_END_OF_TEXT;
}
return new JsonNumber(value);
}
private JsonString readString() {
strip();
if (chars[position] != '"') {
throw new JsonException("Expected opening '\"'");
}
position++;
String value = "";
while (position < chars.length && chars[position] != '"') {
value += chars[position++];
}
if (position == chars.length) {
throw UNEXPECTED_END_OF_TEXT;
}
if (chars[position] != '"') {
throw new JsonException("Expected closing '\"'");
}
position++;
return new JsonString(value);
}
private void readOpeningBrace() {
strip();
if (chars[position] != '{') {
throw new JsonException("Expected '{', found " + chars[position]);
}
position++;
}
private void readClosingBrace() {
strip();
if (chars[position] != CLOSING_BRACE) {
throw new JsonException("Expected '}'");
}
position++;
}
private char peek() {
strip();
return chars[position];
}
private String readKey() {
strip();
if (chars[position] != '"') {
throw new JsonException("Expected opening \"");
}
position++;
String key = "";
while (position < chars.length && chars[position] != '"') {
key += chars[position++];
}
if (position == chars.length) {
throw UNEXPECTED_END_OF_TEXT;
}
if (chars[position] != '"') {
throw new JsonException("Expected closing \"");
}
position++;
return key;
}
private void readColon() {
strip();
if (chars[position] != ':') {
throw new JsonException("Expected ':'");
}
position++;
}
private void readComma() {
strip();
if (chars[position] != COMMA) {
throw new JsonException("Expected ','");
}
position++;
}
private void strip() {
while (position < chars.length && chars[position] == ' ') {
position++;
}
if (position == chars.length) {
throw UNEXPECTED_END_OF_TEXT;
}
}
}
class JsonObject {
private Map<String, JsonObject> map;
public JsonObject() {
map = new HashMap<>();
}
public void put(String key, JsonObject object) {
map.put(key, object);
}
@Override
public String toString() {
return toString("");
}
public String toString(String indent) {
String str = "{\n";
int totalEntries = map.entrySet().size();
int count = 0;
for (Map.Entry<String, JsonObject> entry : map.entrySet()) {
str += indent + " " + "\"" + entry.getKey() + "\": " + entry.getValue().toString(indent + " ");
count++;
if (count < totalEntries) {
str += ", ";
}
}
str += "\n" + indent + "}";
return str;
}
}
class JsonNumber extends JsonObject {
private final long value;
public JsonNumber(long value) {
this.value = value;
}
public String toString(String indent) {
return toString();
}
@Override
public String toString() {
return value + "";
}
}
class JsonString extends JsonObject {
private final String value;
public JsonString(String value) {
this.value = value;
}
public String toString(String indent) {
return toString();
}
@Override
public String toString() {
return "\"" + value.replace("\"", "\\") + "\"";
}
}
class JsonException extends RuntimeException {
public JsonException(String message) {
super(message);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment