/**
* Copyright 2008 - 2012
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* @project loon
* @author cping
* @email:javachenpeng@yahoo.com
* @version 0.3.3
*/
package loon.utils.json;
import loon.utils.MathUtils;
public class JSONParser {
public static final String COMMA = ",";
public static final String COLON = ":";
public static final String QUOT = "\"";
public static final String LEFT_BRACE = "{";
public static final String RIGHT_BRACE = "}";
public static final String TRUE = "true";
public static final String FALSE = "false";
public static final String BLANK = " ";
private static final String flag_res = "{}\":,";
private enum State {
START, KEY, VALUE, END
};
public static final JSONObject read(String input) {
return read(input.toCharArray());
}
public static final JSONObject read(char[] input) {
JSONTokenizer tokenizer = new JSONTokenizer(input, flag_res, BLANK,
true);
return parseJSONObject(tokenizer);
}
public static final JSONObject readFile(String path) throws Exception {
JSONTokenizer tokenizer = new JSONTokenizer(null, flag_res, BLANK, true);
tokenizer.read(path);
return parseJSONObject(tokenizer);
}
private static final JSONObject parseJSONObject(JSONTokenizer tokenizer) {
JSONObject currentObject = null;
String currentKey = null;
Object currentValue = null;
boolean isNumber = true, isComma = false;
State state = State.START;
for (; tokenizer.hasMoreTokens();) {
String token = tokenizer.nextToken();
if (LEFT_BRACE.equals(token)) {
if (state == State.START) {
currentObject = new JSONObject();
state = State.KEY;
isComma = true;
} else if (state == State.VALUE) {
tokenizer.putBackToken(token);
currentValue = parseJSONObject(tokenizer);
isNumber = false;
isComma = false;
} else {
throw new RuntimeException("expected JSON Object after {");
}
} else if (RIGHT_BRACE.equals(token)) {
if (currentKey != null && currentValue != null) {
currentObject.put(currentKey, currentValue);
isComma = false;
}
state = State.END;
return currentObject;
} else if (QUOT.equals(token)) {
if (state == State.VALUE) {
isNumber = false;
}
isComma = false;
} else if (COLON.equals(token)) {
if (state == State.KEY) {
state = State.VALUE;
} else {
throw new RuntimeException("expected key before :");
}
} else if (COMMA.equals(token)) {
isComma = false;
if (state == State.VALUE) {
if (currentKey != null && currentValue != null) {
currentObject.put(currentKey, currentValue);
} else {
throw new RuntimeException("missing key or value");
}
state = State.KEY;
} else {
throw new RuntimeException("unexpected ,");
}
} else {
if (isComma) {
if (state == State.KEY) {
currentKey = token;
} else if (state == State.VALUE) {
currentValue = token;
isComma = false;
isNumber = false;
}
} else if (state == State.KEY) {
currentKey = token;
} else if (state == State.VALUE) {
if (isNumber) {
if (TRUE.equalsIgnoreCase(token)
|| FALSE.equalsIgnoreCase(token)) {
currentValue = Boolean.parseBoolean(token);
} else if (MathUtils.isNan(token)) {
try {
currentValue = Float.parseFloat(token);
} catch (NumberFormatException e) {
throw new RuntimeException(
"non number or non boolean value must be enclosed within [\"]");
}
}
} else {
currentValue = token;
}
isNumber = true;
}
}
}
if (state != State.END) {
throw new RuntimeException("missing }");
}
return currentObject;
}
/*public static void main(String[] args) {
String test = "{\"action\":0,\"resource\":\"/motor/A\",\"content\":{\"speed\":360, \"power\":50}}";
try { // JSONObject obj = JSONParser.readFile("assets/skin.json");
JSONObject obj = JSONParser.read(test);
System.out.println(obj);
return;
} catch (Exception e) {
System.out.println(e.getMessage());
}
}*/
}