json

Hi, today I made a json parser or something like that.


public class GJsonObject {

	public String name = "GJsonObject";
	public String value = "empty";

	public GJsonObject parent = null;

	private List<GJsonObject> children = new ArrayList<GJsonObject>();

	public GJsonObject() {
	}

	public GJsonObject(String name, String value) {
		this.name = name;
		this.value = value;
	}

	public GJsonObject findNode(String node) {

		if (name.equals(node)) return this;

		for (GJsonObject child : children) {
			GJsonObject jsonObject = child.findNode(node);
			if (jsonObject != null) return jsonObject;
		}
		return null;
	}

	public void add(GJsonObject json) {
		json.parent = this;
		children.add(json);
	}

	public static GJsonObject parse(String strJson) {

		StringReader reader = new StringReader(strJson);

		GJsonObject lastNode = new GJsonObject();

		try {

			char ch = ' ';

			boolean parsingString = false;
			String string = "";
			boolean readingData = false;

			while (true) {
				int integer = reader.read();
				ch = (char) integer;
				if (integer == -1) break;

				if (!parsingString) {
					// NOT parsing string

					if (ch == '"') {
						// start parsing string
						parsingString = true;
					}

					if (ch == ':') {
						// create new node and load data to it
						GJsonObject newNode = new GJsonObject(string, "");
						lastNode.add(newNode);
						lastNode = newNode;
						readingData = true;
						string = "";
					}

					if (ch == '{') {
						// not parsing data, parsing new nodes
						readingData = false;
					}

					if (ch == ',') {
						// go back to previous node
						lastNode = lastNode.parent;
					}

					if (ch == '}') {
						// go back 2 nodes.

						lastNode = lastNode.parent;
						if (lastNode.parent != null) {
							lastNode = lastNode.parent;
						} else {
							// parent is null, done parsing the file
							break;
						}
					}

				} else {
					// parsing string
					if (ch == '"') {
						// done parsing string
						parsingString = false;

						if (readingData) {
							// was reading data, so store it to last node
							readingData = false;
							lastNode.value = string;
							string = "";
						}
					} else {
						// parse the string
						string += ch;
					}
				}

			}

			reader.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return lastNode;
	}

}

Here you go.

Why did I make it? Because using already made ones is not fun. And this was very good practice… Improving programming skills is never a bad thing.

Here is some code you can test this bad boy on:


{
	"Person": {
		
		"Name": "Jon",
		"Address": "Cool street 7",
		
		"Family": {
			"Mom": "Lila",
			"Son": "Bran"
		},
		
		"phone": "888 8888"
	}
}

EDIT----------
Hmmmmmmm I just realized I need to add support for things like : [4,0,1] instead of : “[4,0,1]”

Yeah I used to think making all the low-level stuff myself was fun too. Then its really “yours”, right?

Eventually you’ll change your mind and you’ll focus on the high level stuff and gladly reuse tools, frameworks and APIs for the low level bits and bops. That way you actually get things done in stead of having to waste your time not only re-inventing the wheel but also maintaining it.

I kinda got a programmer job now… The problem is that so far in 3 weeks all I have done is look at the code their and do literally no real programming or building something…

So I thought I need some exercise in order not to lose my skills. I figured making a UI system would be fun, so I made a json loader too. It was great exercise :stuck_out_tongue:

You got a programming job after only 1 year of experience?

Its a job for a minimum wage, since I have never worked with other people before, mainly didn’t use things like Git, Arcanist and didn’t do any C++ programming.

Basically my wage will increase as I learn these things and become more productive.

I got hired, because they said I have a lot of potential. My Galaga game was actually a demo game for that job I had to make :smiley:

EDIT–
Ow, did I mention? I quit high school after finishing 10/12 years.

Here is another JSON parser. It’s a recursive descent parser and should be able to handle all standard json code.

import java.util.*;
import java.io.*;

class JSON {
    static LinkedList<Object> tokenize(Scanner in) {
        LinkedList<Object> list = new LinkedList<>();
        while(true) {
            in.skip("\\s*");
            String token = in.findWithinHorizon(",|:|\\[|\\]|\\{|\\}|\".*?\"|'.*?'|true|false|null|\\d*\\.\\d*|\\d+", 0);
            if(token == null) {
                if(in.hasNext()) throw new RuntimeException();
                else return list;
            }
            char c = token.charAt(0);
            if(c == '"' && token.endsWith("\"") || c == '\'' && token.endsWith("'")) list.add(token.substring(1, token.length()-1));
            else if(c >= '0' && c <= '9' || c == '.' ) list.add(Double.valueOf(token));
            else if(token.equalsIgnoreCase("true") || token.equalsIgnoreCase("false")) list.add(Boolean.valueOf(token));
            else if(token.equalsIgnoreCase("null")) list.add(null);
            else list.add(token);
        }
    }
    
    static Object parseValue(LinkedList<Object> tokens) {
        Object elem = tokens.pop();
        if(elem.equals("{")) return parseJSON(tokens);
        else if(elem.equals("[")) return parseArray(tokens);
        else return elem;
    }
    
    static List<Object> parseArray(LinkedList<Object> tokens) {
        ArrayList<Object> list = new ArrayList<>();
        if(tokens.peek().equals("]")) {tokens.pop(); return list;}
        while(true) {
            list.add(parseValue(tokens));
            Object elem = tokens.pop();
            if(elem.equals("]")) return list;
            else if(!elem.equals(",")) throw new RuntimeException();
        }
    }
    
    static Map<String, Object> parseJSON(LinkedList<Object> tokens) {
        HashMap<String, Object> map = new HashMap<>();
        if(tokens.peek().equals("}")) {tokens.pop(); return map;}
        while(true) {
            String key = (String)tokens.pop();
            if(!tokens.pop().equals(":")) throw new RuntimeException();
            Object value = parseValue(tokens);
            map.put(key, value);
            Object elem = tokens.pop();
            if(elem.equals("}")) return map;
            else if(!elem.equals(",")) throw new RuntimeException();
        }
    }
    
    static Map<String, Object> parseJSON(Scanner in) {
        LinkedList<Object> tokens = tokenize(in);
        if(!tokens.pop().equals("{")) throw new RuntimeException();
        return parseJSON(tokens);
    }
    
    public static void main(String[] args) throws Exception {
        Scanner in = new Scanner(new File("test.json"));
        Map<String, Object> map = parseJSON(in);
        in.close();
        System.out.println(map);
        
    }
}

Now that you have a JSON Parser you could expand it to a YAML (v1.2) Parser ;D

And +1 for the recursive descent parser :slight_smile: