All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.endreman0.javajson.JavaJson Maven / Gradle / Ivy

There is a newer version: 0.13.0
Show newest version
package io.github.endreman0.javajson;

import io.github.endreman0.javajson.nodes.ArrayNode;
import io.github.endreman0.javajson.nodes.BooleanNode;
import io.github.endreman0.javajson.nodes.Node;
import io.github.endreman0.javajson.nodes.NullNode;
import io.github.endreman0.javajson.nodes.NumberNode;
import io.github.endreman0.javajson.nodes.ObjectNode;
import io.github.endreman0.javajson.nodes.StringNode;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.file.Files;

/**
 * This class contains all of the methods to parse JSON.
 * You can parse from {@link #parse(String) String}s, {@link #parse(File, Charset) File}s, and {@link #parse(InputStream) InputStream}s.
 * @author endreman0
 */
public class JavaJson{
	/**
	 * Parse a JSON node from a string.
	 * 
	 * The passed string can be any JSON node: boolean, number, string, null, object, or array.
	 * 
	 * If an invalid string is passed in, two things could happen:
	 * 
    *
  • If the first character of the string does not match any known JSON node, null will be returned.
  • *
  • If the first character matches a node, but there is an error somewhere else in the the string, an IllegalArgumentException will be thrown.
  • *
* @param json the string to parse * @return the parsed node, or null if error * @throws IllegalArgumentException if error */ public static Node parse(String json){ return parse(CharBuffer.wrap(json)); } /** * Parse a JSON node from a file. * This is a wrapper for {@link #parse(String)}. It reads the file into a StringBuilder, then parses it with the aforementioned * method. See that method's documentation for more information. * @param file the file to parse * @param charset the file's charset * @return the parsed node, or null if error (see {@link #parse(String)}) * @throws IOException passed from the file reader * @throws IllegalArgumentException if error (see {@link #parse(String)}) */ public static Node parse(File file, Charset charset) throws IOException{ try(BufferedReader reader = Files.newBufferedReader(file.toPath(), charset)){ StringBuilder sb = new StringBuilder(); String line; while((line = reader.readLine()) != null) sb.append(line).append("\r\n"); return parse(sb.toString()); } } /** * Parse a JSON node from an InputStream. * This is a wrapper for {@link #parse(String)}. It reads the stream into a StringBuilder, then parses it with the aforementioned * method. See that method's documentation for more information. * @param in the stream to parse * @return the parsed node, or null if error (see {@link #parse(String)}) * @throws IOException passed from the file reader * @throws IllegalArgumentException if error (see {@link #parse(String)}) */ public static Node parse(InputStream in) throws IOException{ StringBuilder sb = new StringBuilder(); byte[] buffer = new byte[4096]; int read; while(true){ read = in.read(buffer, 0, buffer.length); if(read < buffer.length){ sb.append(new String(buffer).substring(0, read+1)); break; }else{ sb.append(new String(buffer)); } } return parse(CharBuffer.wrap(sb.toString().toCharArray())); } protected static Node parse(CharBuffer json){ char start = json.get(json.position()); if(start == 't' || start == 'f') return parseBoolean(json); else if(Character.isDigit(start)) return parseNumber(json); else if(start == '\"') return parseString(json); else if(start == '[') return parseArray(json); else if(start == '{') return parseObject(json); else if(start == 'n') return parseNull(json); else return null; } protected static BooleanNode parseBoolean(CharBuffer json){ char first = json.get(); if(first == 't'){ if(json.get() == 'r' && json.get() == 'u' && json.get() == 'e') return new BooleanNode(true); else return null; }else if(first == 'f'){ if(json.get() == 'a' && json.get() == 'l' && json.get() == 's' && json.get() == 'e') return new BooleanNode(false); else return null; }else return null; } protected static NumberNode parseNumber(CharBuffer json){ StringBuffer data = new StringBuffer(); char next; while(json.hasRemaining()){ next = json.get(json.position()); if(Character.isDigit(next) || next == '.'){//If the character is a number or decimal point, data.append(next);//append it to the StringBuilder, json.get();//and advance the buffer past it. }else break; } return new NumberNode(Double.valueOf(data.toString())); } protected static StringNode parseString(CharBuffer json){ if(json.get() != '\"') return null; StringBuffer data = new StringBuffer(); char next; while((next = json.get()) != '\"') data.append(next); return new StringNode(data.toString()); } protected static ArrayNode parseArray(CharBuffer json){ if(json.get() != '[') return null; ArrayNode node = new ArrayNode(); while(json.hasRemaining()){ trim(json); node.add(parse(json)); trim(json); if(json.get(json.position()) == ']'){ json.get(); break; } expect(json.get(), ','); } return node; } protected static ObjectNode parseObject(CharBuffer json){ expect(json.get(), '{'); ObjectNode node = new ObjectNode(); trim(json); while(json.hasRemaining() && json.get(json.position()) != '}'){ expect(json.get(), '\"');//Leading quote of the key String key = readFor(json, false, '\"');//Read until the end quote trim(json);//Trim away any spaces or newlines expect(json.get(), ':'); trim(json); Node value = parse(json);//After the colon, the next item is the value for the previous key node.put(key, value); trim(json); if(json.get(json.position()) == '}'){//End of the object is reached json.get();//Advance past the bracket break;//End parsing - it's the end of the object } expect(json.get(), ',');//If it's not the end, read the comma for the next field and read the next field. trim(json); } return node; } protected static NullNode parseNull(CharBuffer json){ if(json.get() == 'n' && json.get() == 'u' && json.get() == 'l' && json.get() == 'l') return new NullNode(); else return null; } protected static String readFor(CharBuffer json, boolean trim, char... targets){ StringBuilder buffer = new StringBuilder(); char next; loop: while(json.hasRemaining()){ next = json.get(); for(char target : targets) if(next == target) break loop; if(trim && (next == ' ' || next == '\r' || next == '\n' || next == '\t')) ;//Don't copy spacers if trimming is enabled else buffer.append(next); } return buffer.toString(); } protected static void trim(CharBuffer json){ char next; while(json.hasRemaining()){ next = json.get(json.position()); if(next == ' ' || next == '\r' || next == '\n' || next == '\t')json.get();//Clear the character out else break;//Stop trimming once the end of the trimmable characters is reached } } protected static void expect(char actual, char... expected){ boolean isExpected = false;//Matches an expected character for(char c : expected) if(actual == c) isExpected = true; if(!isExpected){//Exception time! StringBuffer message = new StringBuffer("Expected chars ["); for(int i=0;i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy