org.mozilla.javascript.json.JsonParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rhino Show documentation
Show all versions of rhino Show documentation
The Rhino JavaScript Engine for Java
The newest version!
/* -*- Mode: java; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.javascript.json;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptRuntime;
import java.util.ArrayList;
import java.util.List;
/**
* This class converts a stream of JSON tokens into a JSON value.
*
* See ECMA 15.12.
* @author Raphael Speyer
* @author Hannes Wallnoefer
*/
public class JsonParser {
private Context cx;
private Scriptable scope;
private int pos;
private int length;
private String src;
public JsonParser(Context cx, Scriptable scope) {
this.cx = cx;
this.scope = scope;
}
public synchronized Object parseValue(String json) throws ParseException {
if (json == null) {
throw new ParseException("Input string may not be null");
}
pos = 0;
length = json.length();
src = json;
Object value = readValue();
consumeWhitespace();
if (pos < length) {
throw new ParseException("Expected end of stream at char " + pos);
}
return value;
}
private Object readValue() throws ParseException {
consumeWhitespace();
while (pos < length) {
char c = src.charAt(pos++);
switch (c) {
case '{':
return readObject();
case '[':
return readArray();
case 't':
return readTrue();
case 'f':
return readFalse();
case '"':
return readString();
case 'n':
return readNull();
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '0':
case '-':
return readNumber(c);
default:
throw new ParseException("Unexpected token: " + c);
}
}
throw new ParseException("Empty JSON string");
}
private Object readObject() throws ParseException {
consumeWhitespace();
Scriptable object = cx.newObject(scope);
// handle empty object literal case early
if (pos < length && src.charAt(pos) == '}') {
pos += 1;
return object;
}
String id;
Object value;
boolean needsComma = false;
while (pos < length) {
char c = src.charAt(pos++);
switch(c) {
case '}':
if (!needsComma) {
throw new ParseException("Unexpected comma in object literal");
}
return object;
case ',':
if (!needsComma) {
throw new ParseException("Unexpected comma in object literal");
}
needsComma = false;
break;
case '"':
if (needsComma) {
throw new ParseException("Missing comma in object literal");
}
id = readString();
consume(':');
value = readValue();
long index = ScriptRuntime.indexFromString(id);
if (index < 0) {
object.put(id, object, value);
} else {
object.put((int)index, object, value);
}
needsComma = true;
break;
default:
throw new ParseException("Unexpected token in object literal");
}
consumeWhitespace();
}
throw new ParseException("Unterminated object literal");
}
private Object readArray() throws ParseException {
consumeWhitespace();
// handle empty array literal case early
if (pos < length && src.charAt(pos) == ']') {
pos += 1;
return cx.newArray(scope, 0);
}
List
© 2015 - 2024 Weber Informatics LLC | Privacy Policy