org.nutz.json.impl.JsonCompileImplV2 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of nutz Show documentation
Show all versions of nutz Show documentation
Nutz, which is a collections of lightweight frameworks, each of them can be used independently
package org.nutz.json.impl;
import java.io.IOException;
import java.io.Reader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.nutz.conf.NutConf;
import org.nutz.json.JsonException;
import org.nutz.json.JsonParser;
import org.nutz.lang.Lang;
import org.nutz.lang.Nums;
import org.nutz.lang.util.NutMap;
import org.nutz.mapl.MaplCompile;
/**
* 将json理解为Map+List,以Token的方式读取,避免回溯等操作
*
* @author wendal([email protected])
*
*/
public class JsonCompileImplV2 implements JsonParser, MaplCompile {
@Override
public Object parse(Reader reader) {
return new JsonTokenScan(reader).read();
}
}
final class JsonTokenScan {
// private static final Log log = Logs.get();
Reader reader;
JsonToken token = new JsonToken();
JsonToken nextToken = null;
JsonToken nextToken2 = new JsonToken();
static final Object END = new Object();
static final Object COMMA = new Object();
public JsonTokenScan(Reader reader) {
this.reader = reader;
}
protected void _nextToken() {
switch (token.type) {
case MapStart:
case MapEnd:
case ListStart:
case ListEnd:
case MapPair:
case Comma:
return;
case '\'':
token.type = SimpleString;
token.value = readString('\'');
return;
case '\"':
token.type = SimpleString;
token.value = readString('"');
return;
case ' ':
case '\t':
case '\n':
case '\r':
char c = 0;
while (true) {
c = nextChar();
switch (c) {
case ' ':
case '\t':
case '\n':
case '\r':
continue;
default:
}
break;
}
token.type = c;
_nextToken();
return;
case '/':
// 看来是注释哦
skipComment();
nextToken();
return;
default:
StringBuilder sb = new StringBuilder();
sb.append((char) token.type);
// 看来只是尝试找到结束字符了
OUT: while (true) {
c = nextChar();
switch (c) {
case MapStart:
case MapEnd:
case ListStart:
case ListEnd:
case MapPair:
case Comma:
nextToken = nextToken2;
nextToken.type = c;
// log.debug("Break OtherString token : " + (char) c);
// log.debug("OtherString token : " + (char) token.type);
break OUT;
case ' ':
case '\t':
case '\r':
case '\n':
break OUT;
case '/':
skipComment();
break OUT;
default:
}
sb.append(c);
}
token.type = OtherString;
token.value = sb.toString();
// log.debug("OtherString Token > " + token.value);
return;
}
}
protected void nextToken() {
if (nextToken != null) {
token.type = nextToken.type;
token.value = nextToken.value;
nextToken = null;
return;
}
token.type = nextChar();
_nextToken();
// log.debug("token: " + token);
}
protected void skipComment() {
char c = nextChar();
switch (c) {
case '/': // 单行注释
while (nextChar() != '\n') {}
// nextToken();
return;
case '*':
char c2 = c;
while (true) {
while ((c = nextChar()) != '/') {
c2 = c;
}
if (c2 == '*') {
return;
}
}
default:
throw unexpectChar(c);
}
}
protected String readString(char endEnd) {
StringBuilder sb = new StringBuilder();
char c = 0;
while ((c = nextChar()) != endEnd) {
switch (c) {
case '\\':
char c2 = parseSp();
if (c == c2 && NutConf.JSON_APPEND_ILLEGAL_ESCAPE) {
sb.append('\\');
}
c = c2;
break;
default:
}
sb.append(c);
}
return sb.toString();
}
protected Map readMap() {
Map map = new NutMap();
boolean hasComma = false;
OUT: while (true) {
nextToken();
switch (token.type) {
case MapEnd:
break OUT;
case SimpleString:
case OtherString:
String key = token.value;
// log.debug("key=" + key + " " + token);
nextToken();
if (token.type != MapPair) {
throw unexpectChar((char) token.type);
}
Object obj = readObject(MapEnd);
if (obj == COMMA) {
if (hasComma) {
throw unexpectChar((char) Comma);
}
hasComma = true;
continue;
}
if (obj == END) {
throw unexpectChar((char) token.type);
}
map.put(key, obj);
hasComma = false;
break;
case Comma:
continue;
default:
throw unexpectChar((char) token.type);
}
}
return map;
}
protected List