Skip to content

Commit

Permalink
0.1.0 - Initial commit of JSON parsing code from JParserDataTypeLike
Browse files Browse the repository at this point in the history
  • Loading branch information
TeamworkGuy2 committed Sep 1, 2016
0 parents commit 6c02195
Show file tree
Hide file tree
Showing 12 changed files with 841 additions and 0 deletions.
16 changes: 16 additions & 0 deletions .classpath
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="test"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="lib" path="C:/Users/TeamworkGuy2/Documents/Java/Libraries/jarray-util/bin/jarray_util.jar" sourcepath="/JArrayUtil"/>
<classpathentry kind="lib" path="C:/Users/TeamworkGuy2/Documents/Java/Libraries/jfunc/bin/jfunc.jar" sourcepath="/JFunc"/>
<classpathentry kind="lib" path="C:/Users/TeamworkGuy2/Documents/Java/Libraries/jprimitive-collections/bin/jprimitive_collections.jar" sourcepath="/JPrimitiveCollections"/>
<classpathentry kind="lib" path="C:/Users/TeamworkGuy2/Documents/Java/Libraries/jrange/bin/jrange.jar" sourcepath="/JRange"/>
<classpathentry kind="lib" path="C:/Users/TeamworkGuy2/Documents/Java/Libraries/jstreamish/bin/jstreamish.jar" sourcepath="/JStreamish"/>
<classpathentry kind="lib" path="C:/Users/TeamworkGuy2/Documents/Java/Libraries/jtext-parser/bin/jtext_parser.jar" sourcepath="/JTextParser"/>
<classpathentry kind="lib" path="C:/Users/TeamworkGuy2/Documents/Java/Libraries/jtext-util/bin/jtext_util.jar" sourcepath="/JTextUtil"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/TestChecks"/>
<classpathentry kind="output" path="bin"/>
</classpath>
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Change Log
All notable changes to this project will be documented in this file.
This project does its best to adhere to [Semantic Versioning](http://semver.org/).


--------
###[0.1.0](N/A) - 2016-09-01
Includes simple JSON parsing code from [JParserDataTypeLike](https://github.com/TeamworkGuy2/JParserDataTypeLike) which came from [JLikelyParser](https://github.com/TeamworkGuy2/JLikelyParser).
* twg2.parser.jsonLite - for parsing JSON like arrays, strings, and numbers
20 changes: 20 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
The MIT License (MIT)

Copyright (c) 2015 TeamworkGuy2

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
JParserJsonLite
==============
version: 0.1.0

####twg2.parser.jsonLite
for parsing JSON like arrays, numbers, and strings, as well as arrays with none quoted strings.
'JSON like' meaning it supports most common JSON syntax or a superset (such as unquoted property names), but may not support the [JSON spec](http://json.org/)
Binary file added bin/jparser_json_lite-with-tests.jar
Binary file not shown.
Binary file added bin/jparser_json_lite.jar
Binary file not shown.
12 changes: 12 additions & 0 deletions package-lib.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version" : "0.1.0",
"name" : "jparser-json-lite",
"description" : "Simple parsing for JSON strings/files",
"homepage" : "https://github.com/TeamworkGuy2/JParserJsonLite",
"license" : "MIT",
"main" : "./bin/jparser_json_lite.jar",
"dependencies" : {
"jtext-parser": "*",
"jtext-util": "*"
}
}
88 changes: 88 additions & 0 deletions src/twg2/parser/jsonLite/JsonLite.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package twg2.parser.jsonLite;


/**
* @author TeamworkGuy2
* @since 2014-9-2
*/
public class JsonLite {
/**
* @author TeamworkGuy2
* @since 2014-9-2
*/
public enum AllTypes {
OBJECT,
ARRAY,
STRING,
NUMBER,
TRUE,
FALSE,
NULL;
}


/**
* @author TeamworkGuy2
* @since 2014-9-2
*/
public enum NumberType {
INTEGER("int"),
LONG("long"),
FLOAT("float"),
DOUBLE("double");

final String primitiveTypeName;


NumberType(String primitiveTypeName) {
this.primitiveTypeName = primitiveTypeName;
}


public static final boolean isInt(JsonLite.NumberType numType) {
return numType != null && numType == NumberType.INTEGER;
}


public static final boolean isLong(JsonLite.NumberType numType) {
return numType != null && numType == NumberType.LONG;
}


public static final boolean isFloat(JsonLite.NumberType numType) {
return numType != null && numType == NumberType.FLOAT;
}


public static final boolean isDouble(JsonLite.NumberType numType) {
return numType != null && numType == NumberType.DOUBLE;
}


public static final boolean isIntLike(JsonLite.NumberType numType) {
return numType != null && (numType == NumberType.INTEGER);
}


public static final boolean isLongLike(JsonLite.NumberType numType) {
return numType != null && (numType == NumberType.LONG || numType == NumberType.INTEGER);
}


public static final boolean isFloatLike(JsonLite.NumberType numType) {
return numType != null && (numType == NumberType.FLOAT || numType == NumberType.INTEGER);
}


public static final boolean isDoubleLike(JsonLite.NumberType numType) {
return numType != null && (numType == NumberType.DOUBLE || numType == NumberType.FLOAT || numType == NumberType.INTEGER || numType == NumberType.LONG);
}


public String getPrimitiveTypeName() {
return primitiveTypeName;
}

}

}
236 changes: 236 additions & 0 deletions src/twg2/parser/jsonLite/JsonLiteArray.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
package twg2.parser.jsonLite;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.List;

import twg2.parser.textParser.TextParser;
import twg2.parser.textParser.TextParserImpl;
import twg2.parser.textParserUtils.ReadIsMatching;
import twg2.parser.textParserUtils.ReadMatching;
import twg2.parser.textParserUtils.ReadWhitespace;
import twg2.text.stringEscape.StringEscape;
import twg2.text.stringUtils.StringCheck;

/**
* @author TeamworkGuy2
* @since 2014-9-2
*/
public class JsonLiteArray {
private static final char ARRAY_START = '[';
private static final char ARRAY_END = ']';
//private static final char[] notStringArrayLike = new char[] {' '/*space*/, ' '/*tab*/, ',', ARRAY_END};


/** Convert an array of strings to a JSON styled array of strings (i.e. {@code ["a", "b", "c"]})
*/
public static final String stringifyArray(List<String> ary) throws IOException {
StringBuilder strB = new StringBuilder(ary.size() > 10 ? ary.size() > 20 ? 128 : 64 : 32);
strB.append(ARRAY_START);
if(ary.size() > 0) {
for(int i = 0, size = ary.size() - 1; i < size; i++) {
strB.append('"');
// replace \ and " with \\ and \"
StringEscape.escape(ary.get(i), '\\', '\\', '"', strB);
strB.append("\", ");
}
strB.append('"');
StringEscape.escape(ary.get(ary.size()-1), '\\', '\\', '"', strB);
strB.append('"');
}
strB.append(ARRAY_END);

return strB.toString();
}


/**
* @see #parseArray(String, List)
*/
public static final List<String> parseArray(String arrayString) {
List<String> ary = new ArrayList<>();
parseArray(arrayString, ary);
return ary;
}


/**
* @see JsonLiteArray#parseArray(TextParser, boolean, List)
*/
public static final void parseArray(String arrayString, List<String> dst) {
parseArray(TextParserImpl.of(arrayString), true, dst);
}


/** Parses a JSON style array where the strings do not need to be quoted.
* Supports the following formats:<br>
* {@code [multiple words, 123, false]} parses to {@code ["multiple words", "123", "false"]}<br>
* {@code [string with "comma, separator", last]} parses to {@code ["string with "comma, separator"", "last"]}<br>
* {@code ["bilbo baggins", middle earth]} parses to {@code ["bilbo baggins", "middle earth"]}
*
* @param in the {@link TextParser} to read from
* @param readLeadingArrayWhitespace true to read leading whitespace before the array, false to not
* @param dst the destination list to store the parsed array elements in
*/
public static final void parseArray(TextParser in, boolean readLeadingArrayWhitespace, List<String> dst) {
@SuppressWarnings({ "unchecked", "rawtypes" })
List<Object> dstList = (List)dst;
parseArrayLike(in, readLeadingArrayWhitespace, true, ',', false, StringCheck.SIMPLE_WHITESPACE, true, ARRAY_START, true, ARRAY_END, false, dstList);
}


/** Read a JSON array with leading element whitespace, required '[' ']' start and end chars,
* and {@link StringCheck#SIMPLE_WHITESPACE} whitespace characters
* @see #parseArrayLike
*/
public static final void parseArrayDeep(TextParser in, boolean readLeadingArrayWhitespace, List<Object> dst) {
parseArrayLike(in, readLeadingArrayWhitespace, true, ',', false, StringCheck.SIMPLE_WHITESPACE, true, ARRAY_START, true, ARRAY_END, true, dst);
}


/** Read a JSON style array with no start mark, with leading array and element whitespace,
* no newlines inside elements, and {@link StringCheck#SIMPLE_WHITESPACE} whitespace characters
* @see #parseArrayLike
*/
public static final void parseArrayLine(TextParser in, boolean readLeadingArrayWhitespace, List<String> dst) {
parseArrayLikeLine(in, readLeadingArrayWhitespace, true, false, StringCheck.SIMPLE_WHITESPACE, dst);
}


/** Read a JSON array with leading element whitespace, required '[' ']' start and end chars,
* and {@link StringCheck#SIMPLE_WHITESPACE} whitespace characters
* @see #parseArrayLike
*/
public static final void parseArrayLineDeep(TextParser in, boolean readLeadingArrayWhitespace, boolean readLeadingElementWhitespace, List<Object> dst) {
parseArrayLike(in, readLeadingArrayWhitespace, readLeadingElementWhitespace, ',', false, StringCheck.SIMPLE_WHITESPACE, false, ARRAY_START, false, ARRAY_END, true, dst);
}


/** Read a JSON style array with no start mark that ends at the end of the current line
* @see #parseArrayLike
*/
public static final void parseArrayLikeLine(TextParser in, boolean readLeadingArrayWhitespace, boolean readLeadingElementWhitespace, boolean allowNewlineInElement,
char[] whitespace, List<String> dst) {
@SuppressWarnings({ "unchecked", "rawtypes" })
List<Object> dstList = (List)dst;
parseArrayLike(in, readLeadingArrayWhitespace, readLeadingElementWhitespace, ',', false, whitespace, false, '\0', false, '\n', false, dstList);
}


/** Read JSON like array with options to read a single line, customize the element separator char, allow newlines, etc.<br>
* For example, to read a JSON style array with leading whitespace, call:<br>
* <pre>parseArrayLike(in, true, true, ',', false, new char[] { ' ', '\t', '\n' }, true, '[', ']', dst);</pre>
*
* @param in the char source to read from
* @param readLeadingArrayWhitespace true to read leading {@code whitespace} chars before checking for the {@code startChar}
* @param readLeadingElementWhitespace true to read leading {@code whitespace} chars before reading each array element
* @param elementSeparator the char that separates array elements, does not apply if it appears inside a quoted string element
* @param allowNewlineInElement true if newlines are allowed inside element strings/text
* @param whitespace the legal whitespace characters when {@code readLeadingArrayWhitespace}
* or {@code readLeadingElementWhitespace} are true
* @param requireStartChar true if a start character is required before the first array element is read
* @param startChar the start character to read if {@code requireStartChar} is true
* @param requireEndChar true if the end character is required after the last element is read
* @param endChar the required end char to read (this character marks the end of the
* array only when it appears between elements where an {@code elementSeparator} is expected)
* @param dst the parsed element strings or nested lists of strings are added to the end of this list
*/
public static final void parseArrayLike(TextParser in, boolean readLeadingArrayWhitespace, boolean readLeadingElementWhitespace,
char elementSeparator, boolean allowNewlineInElement, char[] whitespace,
boolean requireStartChar, char startChar, boolean requireEndChar, char endChar, boolean allowNestedArrays, List<Object> dst) {
char escapeChar = '"';
char replaceChar = '\\';
char newlineChar = '\n';
StringBuilder strDst = new StringBuilder();
boolean foundEnd = false;
if(readLeadingArrayWhitespace) {
ReadWhitespace.readWhitespaceCustom(in, whitespace);
}
// require the first character to be an array start
if(requireStartChar && !in.nextIf(startChar)) {
throw new IllegalStateException("an array must start with '" + startChar + "'");
}
if(requireEndChar && !in.hasNext()) { throw new IllegalStateException("could not find end of array '" + endChar + "'"); }

for(int i = 0; in.hasNext(); i++) {
int startElemPos = in.getPosition();

if(readLeadingElementWhitespace) {
ReadWhitespace.readWhitespaceCustom(in, whitespace);
}

if((i == 0 && in.nextIf(endChar)) || (!requireEndChar && !in.hasNext())) {
foundEnd = true;
break;
}

strDst.setLength(0);
// read nested array
if(allowNestedArrays && ReadIsMatching.isNext(in, startChar)) {
ArrayList<Object> nestedDst = new ArrayList<>();
JsonLiteArray.parseArrayLike(in, readLeadingArrayWhitespace, readLeadingElementWhitespace, elementSeparator, allowNewlineInElement, whitespace,
true, startChar, true, endChar, allowNestedArrays, nestedDst);
dst.add(nestedDst);
// the nested array is required to have a closing char so can safely read trailing whitespace, for example in "[a, [b] ]"
ReadWhitespace.readWhitespaceCustom(in, whitespace);
}
// read normal array element (string or partially quoted string)
else {
JsonLiteArray.readArrayElementLike(in, replaceChar, escapeChar, elementSeparator, endChar, allowNewlineInElement, newlineChar, strDst);
dst.add(strDst.toString());
}

if(in.nextIf(endChar)) {
// leave the ending char and mark end of array reached
foundEnd = true;
break;
}
// read end char since readArrayElementLike does not read the ending char (it could be either ',' or ']')
in.unread(1);
boolean prevCharWasElemSeparator = false;
if(!(prevCharWasElemSeparator = in.nextIf(elementSeparator)) || startElemPos == in.getPosition()) {
if(!prevCharWasElemSeparator) {
in.nextChar();
}
in.nextIf(elementSeparator);
}
}

if(requireEndChar && !foundEnd) { throw new IllegalStateException("could not find end of array '" + endChar + "'"); }
}


/**
* @param in
* @param chReplace
* @param chEsc
* @param chEnd
* @param allowNewline
* @param newlineChar
* @param dst
* @return true if the read string contained a quoted section part way through it,
* false if it contained no quotes or was fully quoted
*/
public static final boolean readArrayElementLike(TextParser in, char chReplace, char chEsc, char chEnd, char chEnd2, boolean allowNewline, char newlineChar, Appendable dst) {
boolean partialQuoted = false;
try {
int readUnescaped = in.nextIfNot(chEsc, chEnd, chEnd2, 0, dst);
if(in.nextIf(chEsc)) {
partialQuoted = true;
if(readUnescaped > 0) {
dst.append(chEsc);
}
ReadMatching.readUnescape(in, chReplace, chEsc, allowNewline, newlineChar, dst);
if(readUnescaped > 0) {
dst.append(chEsc);
}
in.nextIf(chEnd);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
return partialQuoted;
}

}
Loading

0 comments on commit 6c02195

Please sign in to comment.