package com.alibaba.fastjson;
import static com.alibaba.fastjson.JSONStreamContext.ArrayValue;
import static com.alibaba.fastjson.JSONStreamContext.PropertyKey;
import static com.alibaba.fastjson.JSONStreamContext.PropertyValue;
import static com.alibaba.fastjson.JSONStreamContext.StartArray;
import static com.alibaba.fastjson.JSONStreamContext.StartObject;
import java.io.Closeable;
import java.io.Reader;
import java.lang.reflect.Type;
import java.util.Map;
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.JSONLexer;
import com.alibaba.fastjson.parser.JSONReaderScanner;
import com.alibaba.fastjson.parser.JSONToken;
import com.alibaba.fastjson.util.IOUtils;
import com.alibaba.fastjson.util.TypeUtils;
public class JSONReader implements Closeable {
private final DefaultJSONParser parser;
private JSONStreamContext context;
public JSONReader(Reader reader){
this(new JSONReaderScanner(reader));
}
public JSONReader(JSONLexer lexer){
this(new DefaultJSONParser(lexer));
}
public JSONReader(DefaultJSONParser parser){
this.parser = parser;
}
public void config(Feature feature, boolean state) {
this.parser.config(feature, state);
}
public void startObject() {
if (context == null) {
context = new JSONStreamContext(null, JSONStreamContext.StartObject);
} else {
startStructure();
context = new JSONStreamContext(context, JSONStreamContext.StartObject);
}
this.parser.accept(JSONToken.LBRACE, JSONToken.IDENTIFIER);
}
public void endObject() {
this.parser.accept(JSONToken.RBRACE);
endStructure();
}
public void startArray() {
if (context == null) {
context = new JSONStreamContext(null, StartArray);
} else {
startStructure();
context = new JSONStreamContext(context, StartArray);
}
this.parser.accept(JSONToken.LBRACKET);
}
public void endArray() {
this.parser.accept(JSONToken.RBRACKET);
endStructure();
}
private void startStructure() {
final int state = context.getState();
switch (state) {
case PropertyKey:
parser.accept(JSONToken.COLON);
break;
case PropertyValue:
case ArrayValue:
parser.accept(JSONToken.COMMA);
break;
case StartArray:
case StartObject:
break;
default:
throw new JSONException("illegal state : " + context.getState());
}
}
private void endStructure() {
context = context.getParent();
if (context == null) {
return;
}
final int state = context.getState();
int newState = -1;
switch (state) {
case PropertyKey:
newState = PropertyValue;
break;
case StartArray:
newState = ArrayValue;
break;
case PropertyValue:
case StartObject:
newState = PropertyKey;
break;
default:
break;
}
if (newState != -1) {
context.setState(newState);
}
}
public boolean hasNext() {
if (context == null) {
throw new JSONException("context is null");
}
final int token = parser.getLexer().token();
final int state = context.getState();
switch (state) {
case StartArray:
case ArrayValue:
return token != JSONToken.RBRACKET;
case StartObject:
case PropertyValue:
return token != JSONToken.RBRACE;
default:
throw new JSONException("illegal state : " + state);
}
}
public void close() {
IOUtils.close(parser);
}
public Integer readInteger() {
Object object;
if (context == null) {
object = parser.parse();
} else {
readBefore();
object = parser.parse();
readAfter();
}
return TypeUtils.castToInt(object);
}
public Long readLong() {
Object object;
if (context == null) {
object = parser.parse();
} else {
readBefore();
object = parser.parse();
readAfter();
}
return TypeUtils.castToLong(object);
}
public String readString() {
Object object;
if (context == null) {
object = parser.parse();
} else {
readBefore();
object = parser.parse();
readAfter();
}
return TypeUtils.castToString(object);
}
public <T> T readObject(TypeReference<T> typeRef) {
return readObject(typeRef.getType());
}
public <T> T readObject(Type type) {
if (context == null) {
return parser.parseObject(type);
}
readBefore();
T object = parser.parseObject(type);
readAfter();
return object;
}
public <T> T readObject(Class<T> type) {
if (context == null) {
return parser.parseObject(type);
}
readBefore();
T object = parser.parseObject(type);
readAfter();
return object;
}
public void readObject(Object object) {
if (context == null) {
parser.parseObject(object);
return;
}
readBefore();
parser.parseObject(object);
readAfter();
}
public Object readObject() {
if (context == null) {
return parser.parse();
}
readBefore();
Object object;
switch (context.getState()) {
case StartObject:
case PropertyValue:
object = parser.parseKey();
break;
default:
object = parser.parse();
break;
}
readAfter();
return object;
}
@SuppressWarnings("rawtypes")
public Object readObject(Map object) {
if (context == null) {
return parser.parseObject(object);
}
readBefore();
Object value = parser.parseObject(object);
readAfter();
return value;
}
private void readBefore() {
int state = context.getState();
// before
switch (state) {
case PropertyKey:
parser.accept(JSONToken.COLON);
break;
case PropertyValue:
parser.accept(JSONToken.COMMA, JSONToken.IDENTIFIER);
break;
case ArrayValue:
parser.accept(JSONToken.COMMA);
break;
case StartObject:
break;
case StartArray:
break;
default:
throw new JSONException("illegal state : " + state);
}
}
private void readAfter() {
int state = context.getState();
int newStat = -1;
switch (state) {
case StartObject:
newStat = PropertyKey;
break;
case PropertyKey:
newStat = PropertyValue;
break;
case PropertyValue:
newStat = PropertyKey;
break;
case ArrayValue:
break;
case StartArray:
newStat = ArrayValue;
break;
default:
throw new JSONException("illegal state : " + state);
}
if (newStat != -1) {
context.setState(newStat);
}
}
}