external.com.alibaba.fastjson.parser.DefaultJSONParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sekiro-api Show documentation
Show all versions of sekiro-api Show documentation
ratel api,used for developer on ratel system,an extension for xposed framewrok,ratel api compatable with original xposed framework
/*
* Copyright 1999-2101 Alibaba Group.
*
* 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.
*/
package external.com.alibaba.fastjson.parser;
import static external.com.alibaba.fastjson.parser.JSONLexer.EOI;
import static external.com.alibaba.fastjson.parser.JSONToken.EOF;
import static external.com.alibaba.fastjson.parser.JSONToken.ERROR;
import static external.com.alibaba.fastjson.parser.JSONToken.FALSE;
import static external.com.alibaba.fastjson.parser.JSONToken.LBRACE;
import static external.com.alibaba.fastjson.parser.JSONToken.LBRACKET;
import static external.com.alibaba.fastjson.parser.JSONToken.LITERAL_FLOAT;
import static external.com.alibaba.fastjson.parser.JSONToken.LITERAL_INT;
import static external.com.alibaba.fastjson.parser.JSONToken.LITERAL_STRING;
import static external.com.alibaba.fastjson.parser.JSONToken.NEW;
import static external.com.alibaba.fastjson.parser.JSONToken.NULL;
import static external.com.alibaba.fastjson.parser.JSONToken.RBRACKET;
import static external.com.alibaba.fastjson.parser.JSONToken.SET;
import static external.com.alibaba.fastjson.parser.JSONToken.TREE_SET;
import static external.com.alibaba.fastjson.parser.JSONToken.TRUE;
import static external.com.alibaba.fastjson.parser.JSONToken.UNDEFINED;
import java.io.Closeable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import external.com.alibaba.fastjson.JSON;
import external.com.alibaba.fastjson.JSONArray;
import external.com.alibaba.fastjson.JSONException;
import external.com.alibaba.fastjson.JSONObject;
import external.com.alibaba.fastjson.parser.deserializer.ExtraProcessor;
import external.com.alibaba.fastjson.parser.deserializer.ExtraTypeProvider;
import external.com.alibaba.fastjson.parser.deserializer.FieldDeserializer;
import external.com.alibaba.fastjson.parser.deserializer.FieldTypeResolver;
import external.com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import external.com.alibaba.fastjson.serializer.IntegerCodec;
import external.com.alibaba.fastjson.serializer.StringCodec;
import external.com.alibaba.fastjson.util.TypeUtils;
/**
* @author wenshao[[email protected]]
*/
public class DefaultJSONParser implements Closeable {
public final SymbolTable symbolTable;
public ParserConfig config;
private String dateFormatPattern = JSON.DEFFAULT_DATE_FORMAT;
private DateFormat dateFormat;
public final JSONLexer lexer;
protected ParseContext contex;
private ParseContext[] contextArray;
private int contextArrayIndex = 0;
private List resolveTaskList;
public final static int NONE = 0;
public final static int NeedToResolve = 1;
public final static int TypeNameRedirect = 2;
public int resolveStatus = NONE;
protected List extraTypeProviders = null;
protected List extraProcessors = null;
public FieldTypeResolver fieldTypeResolver = null;
public String getDateFomartPattern() {
return dateFormatPattern;
}
public DateFormat getDateFormat() {
if (dateFormat == null) {
dateFormat = new SimpleDateFormat(dateFormatPattern, lexer.locale);
dateFormat.setTimeZone(lexer.timeZone);
}
return dateFormat;
}
public void setDateFormat(String dateFormat) {
this.dateFormatPattern = dateFormat;
this.dateFormat = null;
}
public void setDateFomrat(DateFormat dateFormat) {
this.dateFormat = dateFormat;
}
public DefaultJSONParser(String input){
this(input, ParserConfig.global, JSON.DEFAULT_PARSER_FEATURE);
}
public DefaultJSONParser(final String input, final ParserConfig config){
this(new JSONLexer(input, JSON.DEFAULT_PARSER_FEATURE), config);
}
public DefaultJSONParser(final String input, final ParserConfig config, int features){
this(new JSONLexer(input, features), config);
}
public DefaultJSONParser(final char[] input, int length, final ParserConfig config, int features){
this(new JSONLexer(input, length, features), config);
}
public DefaultJSONParser(final JSONLexer lexer){
this(lexer, ParserConfig.global);
}
public DefaultJSONParser(final JSONLexer lexer, final ParserConfig config){
this.lexer = lexer;
this.config = config;
this.symbolTable = config.symbolTable;
if (lexer.ch == '{') {
int index = ++lexer.bp;
lexer.ch = (index >= lexer.len ? //
JSONLexer.EOI //
: lexer.text.charAt(index));
lexer.token = JSONToken.LBRACE;
} else if (lexer.ch == '[') {
int index = ++lexer.bp;
lexer.ch = (index >= lexer.len ? //
JSONLexer.EOI //
: lexer.text.charAt(index));
lexer.token = JSONToken.LBRACKET;
} else {
lexer.nextToken();
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public final Object parseObject(final Map object, Object fieldName) {
final JSONLexer lexer = this.lexer;
int token = lexer.token;
if (token == JSONToken.NULL) {
lexer.nextToken();
return null;
}
if (token != JSONToken.LBRACE && token != JSONToken.COMMA) {
throw new JSONException("syntax error, expect {, actual " + JSONToken.name(token) + ", " + lexer.info());
}
final Map innerMap;
final boolean isJSONObject;
if (object instanceof JSONObject) {
JSONObject jsonObject = (JSONObject) object;
innerMap = jsonObject.getInnerMap();
isJSONObject = true;
} else {
isJSONObject = false;
innerMap = object;
}
//getInnerMap
final boolean allowISO8601DateFormat = (lexer.features & Feature.AllowISO8601DateFormat.mask) != 0;
final boolean disableCircularReferenceDetect = lexer.disableCircularReferenceDetect;
ParseContext context = this.contex;
try {
boolean setContextFlag = false;
for (;;) {
char ch = lexer.ch;
if (ch != '"' //
&& ch != '}') {
lexer.skipWhitespace();
ch = lexer.ch;
}
while (ch == ',') {
lexer.next();
lexer.skipWhitespace();
ch = lexer.ch;
}
boolean isObjectKey = false;
Object key;
if (ch == '"') {
key = lexer.scanSymbol(symbolTable, '"');
ch = lexer.ch;
if (ch != ':') {
lexer.skipWhitespace();
ch = lexer.ch;
if (ch != ':') {
throw new JSONException("expect ':' at " + lexer.pos + ", name " + key);
}
}
} else if (ch == '}') {
// lexer.next();
{
int index = ++lexer.bp;
lexer.ch = (index >= lexer.len //
? EOI //
: lexer.text.charAt(index));
}
lexer.sp = 0; // resetStringPosition
lexer.nextToken(JSONToken.COMMA);
return object;
} else if (ch == '\'') {
key = lexer.scanSymbol(symbolTable, '\'');
if (lexer.ch != ':') {
lexer.skipWhitespace();
}
ch = lexer.ch;
if (ch != ':') {
throw new JSONException("expect ':' at " + lexer.pos);
}
} else if (ch == EOI) {
throw new JSONException("syntax error, " + lexer.info());
} else if (ch == ',') {
throw new JSONException("syntax error, " + lexer.info());
} else if ((ch >= '0' && ch <= '9') || ch == '-') {
lexer.sp = 0; // resetStringPosition
lexer.scanNumber();
try {
if (lexer.token == JSONToken.LITERAL_INT) {
key = lexer.integerValue();
} else {
key = lexer.decimalValue(true);
}
if (isJSONObject) {
key = key.toString();
}
} catch (NumberFormatException ex) {
throw new JSONException("parse number key error, " + lexer.info());
}
ch = lexer.ch;
if (ch != ':') {
throw new JSONException("parse number key error, " + lexer.info());
}
} else if (ch == '{' || ch == '[') {
lexer.nextToken();
key = parse();
isObjectKey = true;
} else {
key = lexer.scanSymbolUnQuoted(symbolTable);
lexer.skipWhitespace();
ch = lexer.ch;
if (ch != ':') {
throw new JSONException("expect ':' at " + lexer.bp + ", actual " + ch);
}
if (isJSONObject) {
key = key.toString();
}
}
if (!isObjectKey) {
// lexer.next();
{
int index = ++lexer.bp;
ch = lexer.ch = (index >= lexer.len //
? EOI //
: lexer.text.charAt(index));
}
// lexer.skipWhitespace();
for (;;) {
if (ch <= ' ' //
&& (ch == ' ' // 32
|| ch == '\n' // 10
|| ch == '\r' // 13
|| ch == '\t' // 9
|| ch == '\f' // 12
|| ch == '\b') // 8
) {
lexer.next();
ch = lexer.ch;
} else {
break;
}
}
} else {
ch = lexer.ch;
}
lexer.sp = 0; // lexer.resetStringPosition();
if (key == JSON.DEFAULT_TYPE_KEY //
&& !lexer.isEnabled(Feature.DisableSpecialKeyDetect)) {
String typeName = lexer.scanSymbol(symbolTable, '"');
boolean allDigits = true;
for (int i = 0; i < typeName.length(); ++i) {
char c = typeName.charAt(i);
if (c < '0' || c > '9') {
allDigits = false;
break;
}
}
Class> clazz = null;
if (!allDigits) {
clazz = config.checkAutoType(typeName, null, lexer.features);
}
if (clazz == null) {
object.put(JSON.DEFAULT_TYPE_KEY, typeName);
continue;
}
lexer.nextToken(JSONToken.COMMA);
if (lexer.token == JSONToken.RBRACE) {
lexer.nextToken(JSONToken.COMMA);
try {
Object instance = null;
ObjectDeserializer deserializer = this.config.getDeserializer(clazz);
if (deserializer instanceof JavaBeanDeserializer) {
JavaBeanDeserializer javaBeanDeserializer = (JavaBeanDeserializer) deserializer;
instance = javaBeanDeserializer.createInstance(this, clazz);
for (Object o : object.entrySet()) {
Map.Entry entry = (Map.Entry) o;
Object entryKey = entry.getKey();
if (entryKey instanceof String) {
FieldDeserializer fieldDeserializer = javaBeanDeserializer.getFieldDeserializer((String) entryKey);
if (fieldDeserializer != null) {
fieldDeserializer.setValue(instance, entry.getValue());
}
}
}
}
if (instance == null) {
if (clazz == Cloneable.class) {
instance = new HashMap();
} else if ("java.util.Collections$EmptyMap".equals(typeName)) {
instance = Collections.emptyMap();
} else {
instance = clazz.newInstance();
}
}
return instance;
} catch (Exception e) {
throw new JSONException("create instance error", e);
}
}
this.resolveStatus = TypeNameRedirect;
if (this.contex != null && !(fieldName instanceof Integer)) {
this.popContext();
}
if (object.size() > 0) {
Object newObj = TypeUtils.cast(object, clazz, this.config);
this.parseObject(newObj);
return newObj;
}
ObjectDeserializer deserializer = config.getDeserializer(clazz);
Object deserialzeObject = deserializer.deserialze(this, clazz, fieldName);
if (deserializer instanceof MapDeserializer) {
this.resolveStatus = NONE;
}
return deserialzeObject;
}
if (key == "$ref" //
&& context != null
&& !lexer.isEnabled(Feature.DisableSpecialKeyDetect)) {
lexer.nextToken(JSONToken.LITERAL_STRING);
if (lexer.token == JSONToken.LITERAL_STRING) {
String ref = lexer.stringVal();
lexer.nextToken(JSONToken.RBRACE);
Object refValue = null;
if ("@".equals(ref)) {
ParseContext thisContext = this.contex;
Object thisObj = thisContext.object;
if (thisObj instanceof Object[] || thisObj instanceof Collection>) {
refValue = thisObj;
} else if (thisContext.parent != null) {
refValue = thisContext.parent.object;
}
} else if ("..".equals(ref)) {
if (context.object != null) {
refValue = context.object;
} else {
addResolveTask(new ResolveTask(context, ref));
resolveStatus = DefaultJSONParser.NeedToResolve;
}
} else if ("$".equals(ref)) {
ParseContext rootContext = context;
while (rootContext.parent != null) {
rootContext = rootContext.parent;
}
if (rootContext.object != null) {
refValue = rootContext.object;
} else {
addResolveTask(new ResolveTask(rootContext, ref));
resolveStatus = DefaultJSONParser.NeedToResolve;
}
} else {
addResolveTask(new ResolveTask(context, ref));
resolveStatus = DefaultJSONParser.NeedToResolve;
}
if (lexer.token != JSONToken.RBRACE) {
throw new JSONException("syntax error, " + lexer.info());
}
lexer.nextToken(JSONToken.COMMA);
return refValue;
} else {
throw new JSONException("illegal ref, " + JSONToken.name(lexer.token));
}
}
if ((!disableCircularReferenceDetect) //
&& !setContextFlag) {
ParseContext contextR = setContext(this.contex, object, fieldName);
if (context == null) {
context = contextR;
}
setContextFlag = true;
}
Object value;
if (ch == '"') {
String strValue = lexer.scanStringValue('"');
value = strValue;
if (allowISO8601DateFormat) {
JSONLexer iso8601Lexer = new JSONLexer(strValue);
if (iso8601Lexer.scanISO8601DateIfMatch(true)) {
value = iso8601Lexer.calendar.getTime();
}
iso8601Lexer.close();
}
if (innerMap != null) {
innerMap.put(key, value);
} else {
object.put(key, value);
}
} else if (ch >= '0' && ch <= '9' || ch == '-') {
value = lexer.scanNumberValue();
innerMap.put(key, value);
} else if (ch == '[') { // 减少嵌套,兼容android
lexer.token = JSONToken.LBRACKET;
// lexer.next();
{
int index = ++lexer.bp;
lexer.ch = (index >= lexer.len //
? EOI //
: lexer.text.charAt(index));
}
ArrayList list = new ArrayList();
final boolean parentIsArray = fieldName != null && fieldName.getClass() == Integer.class;
if (!parentIsArray) {
this.setContext(context);
}
this.parseArray(list, key);
value = new JSONArray(list);
if (innerMap != null) {
innerMap.put(key, value);
} else {
object.put(key, value);
}
token = lexer.token;
if (token == JSONToken.RBRACE) {
lexer.nextToken(JSONToken.COMMA);
return object;
} else if (token == JSONToken.COMMA) {
continue;
} else {
throw new JSONException("syntax error, " + lexer.info());
}
} else if (ch == '{') { // 减少嵌套,兼容android
{
int index = ++lexer.bp;
lexer.ch = (index >= lexer.len //
? EOI //
: lexer.text.charAt(index));
lexer.token = JSONToken.LBRACE;
}
final boolean parentIsArray = fieldName instanceof Integer;
JSONObject input = (lexer.features & Feature.OrderedField.mask) != 0 //
? new JSONObject(new LinkedHashMap()) //
: new JSONObject();
ParseContext ctxLocal = null;
if ((!disableCircularReferenceDetect) //
&& !parentIsArray) {
ctxLocal = setContext(context, input, key);
}
Object obj = null;
boolean objParsed = false;
if (fieldTypeResolver != null) {
String resolveFieldName = key != null ? key.toString() : null;
Type fieldType = fieldTypeResolver.resolve(object, resolveFieldName);
if (fieldType != null) {
ObjectDeserializer fieldDeser = config.getDeserializer(fieldType);
obj = fieldDeser.deserialze(this, fieldType, key);
objParsed = true;
}
}
if (!objParsed) {
obj = this.parseObject(input, key);
}
if (ctxLocal != null && input != obj) {
ctxLocal.object = object;
}
if (resolveStatus == NeedToResolve) {
checkMapResolve(object, key.toString());
}
if (innerMap != null) {
innerMap.put(key, obj);
} else {
object.put(key, obj);
}
if (parentIsArray) {
setContext(context, obj, key);
}
token = lexer.token;
if (token == JSONToken.RBRACE) {
lexer.nextToken(JSONToken.COMMA);
if (!disableCircularReferenceDetect) {
this.contex = context;
}
return object;
} else if (token == JSONToken.COMMA) {
continue;
} else {
throw new JSONException("syntax error, " + lexer.info());
}
} else if (ch == 't') {
if (lexer.text.startsWith("true", lexer.bp)) {
lexer.bp += 3;
lexer.next();
object.put(key, Boolean.TRUE);
}
} else if (ch == 'f') {
if (lexer.text.startsWith("false", lexer.bp)) {
lexer.bp += 4;
lexer.next();
object.put(key, Boolean.FALSE);
}
} else {
lexer.nextToken();
value = parse();
object.put(object.getClass() == JSONObject.class //
? key.toString() //
: key, //
value);
if (lexer.token == JSONToken.RBRACE) {
lexer.nextToken(JSONToken.COMMA);
return object;
} else if (lexer.token == JSONToken.COMMA) {
continue;
} else {
throw new JSONException("syntax error, " + lexer.info());
}
}
ch = lexer.ch;
if (ch != ',' && ch != '}') {
lexer.skipWhitespace();
ch = lexer.ch;
}
if (ch == ',') {
// lexer.next();
{
int index = ++lexer.bp;
lexer.ch = (index >= lexer.len //
? EOI //
: lexer.text.charAt(index));
}
continue;
} else if (ch == '}') {
// lexer.next();
{
int index = ++lexer.bp;
ch = lexer.ch = (index >= lexer.len //
? EOI //
: lexer.text.charAt(index));
}
lexer.sp = 0; // lexer.resetStringPosition();
if (ch == ',') {
int index = ++lexer.bp;
lexer.ch = (index >= lexer.len //
? EOI //
: lexer.text.charAt(index));
lexer.token = JSONToken.COMMA;
} else if (ch == '}') {
int index = ++lexer.bp;
lexer.ch = (index >= lexer.len //
? EOI //
: lexer.text.charAt(index));
lexer.token = JSONToken.RBRACE;
} else if (ch == ']') {
int index = ++lexer.bp;
lexer.ch = (index >= lexer.len //
? EOI //
: lexer.text.charAt(index));
lexer.token = JSONToken.RBRACKET;
} else {
lexer.nextToken();
}
if (!disableCircularReferenceDetect) {
this.setContext(this.contex, object, fieldName);
}
return object;
} else {
throw new JSONException("syntax error, " + lexer.info());
}
}
} finally {
if (!disableCircularReferenceDetect) {
this.contex = context;
}
}
}
// compatible
@SuppressWarnings("unchecked")
public T parseObject(Class clazz) {
return (T) parseObject(clazz, null);
}
public T parseObject(Type type) {
return parseObject(type, null);
}
@SuppressWarnings("unchecked")
public T parseObject(Type type, Object fieldName) {
if (lexer.token == JSONToken.NULL) {
lexer.nextToken();
return null;
}
if (lexer.token == JSONToken.LITERAL_STRING) {
if (type == byte[].class) {
byte[] bytes = lexer.bytesValue();
lexer.nextToken();
return (T) bytes;
}
if (type == char[].class) {
String strVal = lexer.stringVal();
lexer.nextToken();
return (T) strVal.toCharArray();
}
}
ObjectDeserializer derializer = config.getDeserializer(type);
try {
return (T) derializer.deserialze(this, type, fieldName);
} catch (JSONException e) {
throw e;
} catch (Exception e) {
throw new JSONException(e.getMessage(), e);
}
}
public List parseArray(Class clazz) {
List array = new ArrayList();
parseArray(clazz, array);
return array;
}
public void parseArray(Class> clazz, @SuppressWarnings("rawtypes") Collection array) {
parseArray((Type) clazz, array);
}
@SuppressWarnings("rawtypes")
public void parseArray(Type type, Collection array) {
parseArray(type, array, null);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public void parseArray(Type type, Collection array, Object fieldName) {
if (lexer.token == JSONToken.SET || lexer.token == JSONToken.TREE_SET) {
lexer.nextToken();
}
if (lexer.token != JSONToken.LBRACKET) {
throw new JSONException("exepct '[', but " + JSONToken.name(lexer.token) + ", " + lexer.info());
}
ObjectDeserializer deserializer = null;
if (int.class == type) {
deserializer = IntegerCodec.instance;
lexer.nextToken(JSONToken.LITERAL_INT);
} else if (String.class == type) {
deserializer = StringCodec.instance;
lexer.nextToken(JSONToken.LITERAL_STRING);
} else {
deserializer = config.getDeserializer(type);
lexer.nextToken(JSONToken.LBRACE);
}
ParseContext context = this.contex;
if (!lexer.disableCircularReferenceDetect) {
setContext(this.contex, array, fieldName);
}
try {
for (int i = 0;; ++i) {
while (lexer.token == JSONToken.COMMA) {
lexer.nextToken();
continue;
}
if (lexer.token == JSONToken.RBRACKET) {
break;
}
if (int.class == type) {
Object val = IntegerCodec.instance.deserialze(this, null, null);
array.add(val);
} else if (String.class == type) {
String value;
if (lexer.token == JSONToken.LITERAL_STRING) {
value = lexer.stringVal();
lexer.nextToken(JSONToken.COMMA);
} else {
Object obj = this.parse();
value = obj == null //
? null //
: obj.toString();
}
array.add(value);
} else {
Object val;
if (lexer.token == JSONToken.NULL) {
lexer.nextToken();
val = null;
} else {
val = deserializer.deserialze(this, type, i);
}
array.add(val);
if (resolveStatus == NeedToResolve) {
checkListResolve(array);
}
}
if (lexer.token == JSONToken.COMMA) {
lexer.nextToken();
continue;
}
}
} finally {
this.contex = context;
}
lexer.nextToken(JSONToken.COMMA);
}
public Object[] parseArray(Type[] types) {
if (lexer.token == JSONToken.NULL) {
lexer.nextToken(JSONToken.COMMA);
return null;
}
if (lexer.token != JSONToken.LBRACKET) {
throw new JSONException("syntax error, " + lexer.info());
}
Object[] list = new Object[types.length];
if (types.length == 0) {
lexer.nextToken(JSONToken.RBRACKET);
if (lexer.token != JSONToken.RBRACKET) {
throw new JSONException("syntax error, " + lexer.info());
}
lexer.nextToken(JSONToken.COMMA);
return new Object[0];
}
lexer.nextToken(JSONToken.LITERAL_INT);
for (int i = 0; i < types.length; ++i) {
Object value;
if (lexer.token == JSONToken.NULL) {
value = null;
lexer.nextToken(JSONToken.COMMA);
} else {
Type type = types[i];
if (type == int.class || type == Integer.class) {
if (lexer.token == JSONToken.LITERAL_INT) {
value = Integer.valueOf(lexer.intValue());
lexer.nextToken(JSONToken.COMMA);
} else {
value = this.parse();
value = TypeUtils.cast(value, type, config);
}
} else if (type == String.class) {
if (lexer.token == JSONToken.LITERAL_STRING) {
value = lexer.stringVal();
lexer.nextToken(JSONToken.COMMA);
} else {
value = this.parse();
value = TypeUtils.cast(value, type, config);
}
} else {
boolean isArray = false;
Class> componentType = null;
if (i == types.length - 1) {
if (type instanceof Class) {
Class> clazz = (Class>) type;
isArray = clazz.isArray();
componentType = clazz.getComponentType();
}
}
// support varArgs
if (isArray && lexer.token != JSONToken.LBRACKET) {
List