/src/main/java/com/alibaba/fastjson/parser/DefaultJSONParser.java
Java | 1163 lines | 968 code | 170 blank | 25 comment | 250 complexity | f5bf9a75a22eabf0d36fb56360f2d2d8 MD5 | raw file
- /*
- * 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 com.alibaba.fastjson.parser;
- import static com.alibaba.fastjson.parser.JSONScanner.EOI;
- import static com.alibaba.fastjson.parser.JSONToken.EOF;
- import static com.alibaba.fastjson.parser.JSONToken.ERROR;
- import static com.alibaba.fastjson.parser.JSONToken.FALSE;
- import static com.alibaba.fastjson.parser.JSONToken.LBRACE;
- import static com.alibaba.fastjson.parser.JSONToken.LBRACKET;
- import static com.alibaba.fastjson.parser.JSONToken.LITERAL_FLOAT;
- import static com.alibaba.fastjson.parser.JSONToken.LITERAL_INT;
- import static com.alibaba.fastjson.parser.JSONToken.LITERAL_STRING;
- import static com.alibaba.fastjson.parser.JSONToken.NEW;
- import static com.alibaba.fastjson.parser.JSONToken.NULL;
- import static com.alibaba.fastjson.parser.JSONToken.RBRACKET;
- import static com.alibaba.fastjson.parser.JSONToken.SET;
- import static com.alibaba.fastjson.parser.JSONToken.TREE_SET;
- import static com.alibaba.fastjson.parser.JSONToken.TRUE;
- import java.lang.reflect.ParameterizedType;
- import java.lang.reflect.Type;
- import java.lang.reflect.TypeVariable;
- import java.lang.reflect.WildcardType;
- import java.math.BigDecimal;
- import java.math.BigInteger;
- import java.text.DateFormat;
- import java.text.SimpleDateFormat;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Date;
- import java.util.HashSet;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import java.util.TreeSet;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONException;
- import com.alibaba.fastjson.JSONObject;
- import com.alibaba.fastjson.parser.deserializer.DefaultObjectDeserializer;
- import com.alibaba.fastjson.parser.deserializer.FieldDeserializer;
- import com.alibaba.fastjson.parser.deserializer.IntegerDeserializer;
- import com.alibaba.fastjson.parser.deserializer.ListResolveFieldDeserializer;
- import com.alibaba.fastjson.parser.deserializer.MapResolveFieldDeserializer;
- import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
- import com.alibaba.fastjson.parser.deserializer.StringDeserializer;
- import com.alibaba.fastjson.util.TypeUtils;
- /**
- * @author wenshao<szujobs@hotmail.com>
- */
- public class DefaultJSONParser extends AbstractJSONParser {
- protected final Object input;
- protected final SymbolTable symbolTable;
- protected ParserConfig config;
- private DefaultObjectDeserializer derializer = new DefaultObjectDeserializer();
- private final static Set<Class<?>> primitiveClasses = new HashSet<Class<?>>();
- private String dateFormatPattern = JSON.DEFFAULT_DATE_FORMAT;
- private DateFormat dateFormat;
- protected final JSONLexer lexer;
- protected ParseContext context;
- private ParseContext[] contextArray = new ParseContext[8];
- private int contextArrayIndex = 0;
- private final List<ResolveTask> resolveTaskList = new ArrayList<ResolveTask>();
- public final static int NONE = 0;
- public final static int NeedToResolve = 1;
- public final static int TypeNameRedirect = 2;
- private int resolveStatus = NONE;
- static {
- primitiveClasses.add(boolean.class);
- primitiveClasses.add(byte.class);
- primitiveClasses.add(short.class);
- primitiveClasses.add(int.class);
- primitiveClasses.add(long.class);
- primitiveClasses.add(float.class);
- primitiveClasses.add(double.class);
- primitiveClasses.add(Boolean.class);
- primitiveClasses.add(Byte.class);
- primitiveClasses.add(Short.class);
- primitiveClasses.add(Integer.class);
- primitiveClasses.add(Long.class);
- primitiveClasses.add(Float.class);
- primitiveClasses.add(Double.class);
- primitiveClasses.add(BigInteger.class);
- primitiveClasses.add(BigDecimal.class);
- primitiveClasses.add(String.class);
- }
- public String getDateFomartPattern() {
- return dateFormatPattern;
- }
- public DateFormat getDateFormat() {
- if (dateFormat == null) {
- dateFormat = new SimpleDateFormat(dateFormatPattern);
- }
- 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.getGlobalInstance(), JSON.DEFAULT_PARSER_FEATURE);
- }
- public DefaultJSONParser(final String input, final ParserConfig config){
- this(input, new JSONScanner(input, JSON.DEFAULT_PARSER_FEATURE), config);
- }
- public DefaultJSONParser(final String input, final ParserConfig config, int features){
- this(input, new JSONScanner(input, features), config);
- }
- public DefaultJSONParser(final char[] input, int length, final ParserConfig config, int features){
- this(input, new JSONScanner(input, length, features), config);
- }
- public DefaultJSONParser(final Object input, final JSONLexer lexer, final ParserConfig config){
- this.lexer = lexer;
- this.input = input;
- this.config = config;
- this.symbolTable = config.getSymbolTable();
- lexer.nextToken(JSONToken.LBRACE); // prime the pump
- }
- public SymbolTable getSymbolTable() {
- return symbolTable;
- }
- public String getInput() {
- if (input instanceof char[]) {
- return new String((char[]) input);
- }
- return input.toString();
- }
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public final Object parseObject(final Map object, Object fieldName) {
- JSONScanner lexer = (JSONScanner) this.lexer;
- if (lexer.token() != JSONToken.LBRACE && lexer.token() != JSONToken.COMMA) {
- throw new JSONException("syntax error, expect {, actual " + lexer.tokenName());
- }
- ParseContext context = this.getContext();
- try {
- boolean setContextFlag = false;
- for (;;) {
- lexer.skipWhitespace();
- char ch = lexer.getCurrent();
- if (isEnabled(Feature.AllowArbitraryCommas)) {
- while (ch == ',') {
- lexer.incrementBufferPosition();
- lexer.skipWhitespace();
- ch = lexer.getCurrent();
- }
- }
- boolean isObjectKey = false;
- Object key;
- if (ch == '"') {
- key = lexer.scanSymbol(symbolTable, '"');
- lexer.skipWhitespace();
- ch = lexer.getCurrent();
- if (ch != ':') {
- throw new JSONException("expect ':' at " + lexer.pos() + ", name " + key);
- }
- } else if (ch == '}') {
- lexer.incrementBufferPosition();
- lexer.resetStringPosition();
- lexer.nextToken();
- return object;
- } else if (ch == '\'') {
- if (!isEnabled(Feature.AllowSingleQuotes)) {
- throw new JSONException("syntax error");
- }
- key = lexer.scanSymbol(symbolTable, '\'');
- lexer.skipWhitespace();
- ch = lexer.getCurrent();
- if (ch != ':') {
- throw new JSONException("expect ':' at " + lexer.pos());
- }
- } else if (ch == EOI) {
- throw new JSONException("syntax error");
- } else if (ch == ',') {
- throw new JSONException("syntax error");
- } else if ((ch >= '0' && ch <= '9') || ch == '-') {
- lexer.resetStringPosition();
- lexer.scanNumber();
- if (lexer.token() == JSONToken.LITERAL_INT) {
- key = lexer.integerValue();
- } else {
- key = lexer.decimalValue(true);
- }
- ch = lexer.getCurrent();
- if (ch != ':') {
- throw new JSONException("expect ':' at " + lexer.pos() + ", name " + key);
- }
- } else if (ch == '{' || ch == '[') {
- lexer.nextToken();
- key = parse();
- isObjectKey = true;
- } else {
- if (!isEnabled(Feature.AllowUnQuotedFieldNames)) {
- throw new JSONException("syntax error");
- }
- key = lexer.scanSymbolUnQuoted(symbolTable);
- lexer.skipWhitespace();
- ch = lexer.getCurrent();
- if (ch != ':') {
- throw new JSONException("expect ':' at " + lexer.pos() + ", actual " + ch);
- }
- }
- if (!isObjectKey) {
- lexer.incrementBufferPosition();
- lexer.skipWhitespace();
- }
- ch = lexer.getCurrent();
- lexer.resetStringPosition();
- if (key == "@type") {
- String typeName = lexer.scanSymbol(symbolTable, '"');
- Class<?> clazz = TypeUtils.loadClass(typeName);
- if (clazz == null) {
- object.put("@type", typeName);
- continue;
- }
- lexer.nextToken(JSONToken.COMMA);
- if (lexer.token() == JSONToken.RBRACE) {
- lexer.nextToken(JSONToken.COMMA);
- try {
- return clazz.newInstance();
- } catch (Exception e) {
- throw new JSONException("create instance error", e);
- }
- }
- this.setResolveStatus(TypeNameRedirect);
- if (this.context != null && !(fieldName instanceof Integer)) {
- this.popContext();
- }
- ObjectDeserializer deserializer = config.getDeserializer(clazz);
- return deserializer.deserialze(this, clazz, fieldName);
- }
-
- if (key == "$ref") {
- 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)) {
- if (this.getContext() != null) {
- refValue = this.getContext().getObject();
- }
- } else if ("..".equals(ref)) {
- ParseContext parentContext = context.getParentContext();
- if (parentContext.getObject() != null) {
- refValue = this.getContext().getObject();
- } else {
- addResolveTask(new ResolveTask(parentContext, ref));
- setResolveStatus(DefaultJSONParser.NeedToResolve);
- }
- } else if ("$".equals(ref)) {
- ParseContext rootContext = context;
- while (rootContext.getParentContext() != null) {
- rootContext = rootContext.getParentContext();
- }
- if (rootContext.getObject() != null) {
- refValue = rootContext.getObject();
- } else {
- addResolveTask(new ResolveTask(rootContext, ref));
- setResolveStatus(DefaultJSONParser.NeedToResolve);
- }
- } else {
- addResolveTask(new ResolveTask(context, ref));
- setResolveStatus(DefaultJSONParser.NeedToResolve);
- }
- if (lexer.token() != JSONToken.RBRACE) {
- throw new JSONException("syntax error");
- }
- lexer.nextToken(JSONToken.COMMA);
- return refValue;
- } else {
- throw new JSONException("illegal ref, " + JSONToken.name(lexer.token()));
- }
- }
-
- if (!setContextFlag) {
- setContext(object, fieldName);
- setContextFlag = true;
- }
- Object value;
- if (ch == '"') {
- lexer.scanString();
- String strValue = lexer.stringVal();
- value = strValue;
- if (lexer.isEnabled(Feature.AllowISO8601DateFormat)) {
- JSONScanner iso8601Lexer = new JSONScanner(strValue);
- if (iso8601Lexer.scanISO8601DateIfMatch()) {
- value = iso8601Lexer.getCalendar().getTime();
- }
- }
- if (object.getClass() == JSONObject.class) {
- object.put(key.toString(), value);
- } else {
- object.put(key, value);
- }
- } else if (ch >= '0' && ch <= '9' || ch == '-') {
- lexer.scanNumber();
- if (lexer.token() == JSONToken.LITERAL_INT) {
- value = lexer.integerValue();
- } else {
- value = lexer.decimalValue();
- }
- object.put(key, value);
- } else if (ch == '[') { // 减少潜套,兼容android
- lexer.nextToken();
- JSONArray list = new JSONArray();
- this.parseArray(list, key);
- value = list;
- object.put(key, value);
- if (lexer.token() == JSONToken.RBRACE) {
- lexer.nextToken();
- return object;
- } else if (lexer.token() == JSONToken.COMMA) {
- continue;
- } else {
- throw new JSONException("syntax error");
- }
- } else if (ch == '{') { // 减少潜套,兼容android
- lexer.nextToken();
- Object obj = this.parseObject(new JSONObject(), key);
- checkMapResolve(object, key.toString());
- if (object.getClass() == JSONObject.class) {
- object.put(key.toString(), obj);
- } else {
- object.put(key, obj);
- }
- setContext(context, obj, key);
- if (lexer.token() == JSONToken.RBRACE) {
- lexer.nextToken();
- setContext(context);
- return object;
- } else if (lexer.token() == JSONToken.COMMA) {
- continue;
- } else {
- throw new JSONException("syntax error, " + lexer.tokenName());
- }
- } else {
- lexer.nextToken();
- value = parse();
- object.put(key, value);
- if (lexer.token() == JSONToken.RBRACE) {
- lexer.nextToken();
- return object;
- } else if (lexer.token() == JSONToken.COMMA) {
- continue;
- } else {
- throw new JSONException("syntax error, position at " + lexer.pos() + ", name " + key);
- }
- }
- lexer.skipWhitespace();
- ch = lexer.getCurrent();
- if (ch == ',') {
- lexer.incrementBufferPosition();
- continue;
- } else if (ch == '}') {
- lexer.incrementBufferPosition();
- lexer.resetStringPosition();
- lexer.nextToken();
- this.setContext(object, fieldName);
- return object;
- } else {
- throw new JSONException("syntax error, position at " + lexer.pos() + ", name " + key);
- }
- }
- } finally {
- this.setContext(context);
- }
- }
- public ParserConfig getConfig() {
- return config;
- }
- public void setConfig(ParserConfig config) {
- this.config = config;
- }
- // compatible
- @SuppressWarnings("unchecked")
- public <T> T parseObject(Class<T> clazz) {
- return (T) parseObject((Type) clazz);
- }
- @SuppressWarnings("unchecked")
- public <T> T parseObject(Type type) {
- if (lexer.token() == JSONToken.NULL) {
- lexer.nextToken();
- return null;
- }
- ObjectDeserializer derializer = config.getDeserializer(type);
- try {
- return (T) derializer.deserialze(this, type, null);
- } catch (JSONException e) {
- throw e;
- } catch (Throwable e) {
- throw new JSONException(e.getMessage(), e);
- }
- }
- public <T> List<T> parseArray(Class<T> clazz) {
- List<T> array = new ArrayList<T>();
- 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()));
- }
- ObjectDeserializer deserializer = null;
- if (int.class == type) {
- deserializer = IntegerDeserializer.instance;
- lexer.nextToken(JSONToken.LITERAL_INT);
- } else if (String.class == type) {
- deserializer = StringDeserializer.instance;
- lexer.nextToken(JSONToken.LITERAL_STRING);
- } else {
- deserializer = config.getDeserializer(type);
- lexer.nextToken(deserializer.getFastMatchToken());
- }
- ParseContext context = this.getContext();
- this.setContext(array, fieldName);
- try {
- for (int i = 0;; ++i) {
- if (isEnabled(Feature.AllowArbitraryCommas)) {
- while (lexer.token() == JSONToken.COMMA) {
- lexer.nextToken();
- continue;
- }
- }
- if (lexer.token() == JSONToken.RBRACKET) {
- break;
- }
- if (int.class == type) {
- Object val = IntegerDeserializer.deserialze(this);
- 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();
- if (obj == null) {
- value = null;
- } else {
- value = 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);
- checkListResolve(array);
- }
- if (lexer.token() == JSONToken.COMMA) {
- lexer.nextToken(deserializer.getFastMatchToken());
- continue;
- }
- }
- } finally {
- this.setContext(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.tokenName());
- }
- 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.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<Object> varList = new ArrayList<Object>();
- ObjectDeserializer derializer = config.getDeserializer(componentType);
- int fastMatch = derializer.getFastMatchToken();
- if (lexer.token() != JSONToken.RBRACKET) {
- for (;;) {
- Object item = derializer.deserialze(this, type, null);
- varList.add(item);
- if (lexer.token() == JSONToken.COMMA) {
- lexer.nextToken(fastMatch);
- } else if (lexer.token() == JSONToken.RBRACKET) {
- break;
- } else {
- throw new JSONException("syntax error :" + JSONToken.name(lexer.token()));
- }
- }
- }
- value = TypeUtils.cast(varList, type, config);
- } else {
- ObjectDeserializer derializer = config.getDeserializer(type);
- value = derializer.deserialze(this, type, null);
- }
- }
- }
- list[i] = value;
- if (lexer.token() == JSONToken.RBRACKET) {
- break;
- }
- if (lexer.token() != JSONToken.COMMA) {
- throw new JSONException("syntax error :" + JSONToken.name(lexer.token()));
- }
- if (i == types.length - 1) {
- lexer.nextToken(JSONToken.RBRACKET);
- } else {
- lexer.nextToken(JSONToken.LITERAL_INT);
- }
- }
- if (lexer.token() != JSONToken.RBRACKET) {
- throw new JSONException("syntax error");
- }
- lexer.nextToken(JSONToken.COMMA);
- return list;
- }
- public void parseObject(Object object) {
- derializer.parseObject(this, object);
- }
- public Object parseArrayWithType(Type collectionType) {
- if (lexer.token() == JSONToken.NULL) {
- lexer.nextToken();
- return null;
- }
- Type[] actualTypes = ((ParameterizedType) collectionType).getActualTypeArguments();
- if (actualTypes.length != 1) {
- throw new JSONException("not support type " + collectionType);
- }
- Type actualTypeArgument = actualTypes[0];
- if (actualTypeArgument instanceof Class) {
- List<Object> array = new ArrayList<Object>();
- this.parseArray((Class<?>) actualTypeArgument, array);
- return array;
- }
- if (actualTypeArgument instanceof WildcardType) {
- WildcardType wildcardType = (WildcardType) actualTypeArgument;
- // assert wildcardType.getUpperBounds().length == 1;
- Type upperBoundType = wildcardType.getUpperBounds()[0];
- // assert upperBoundType instanceof Class;
- if (Object.class.equals(upperBoundType)) {
- if (wildcardType.getLowerBounds().length == 0) {
- // Collection<?>
- return parse();
- } else {
- throw new JSONException("not support type : " + collectionType);
- }
- }
- List<Object> array = new ArrayList<Object>();
- this.parseArray((Class<?>) upperBoundType, array);
- return array;
- // throw new JSONException("not support type : " +
- // collectionType);return parse();
- }
- if (actualTypeArgument instanceof TypeVariable) {
- TypeVariable<?> typeVariable = (TypeVariable<?>) actualTypeArgument;
- Type[] bounds = typeVariable.getBounds();
- if (bounds.length != 1) {
- throw new JSONException("not support : " + typeVariable);
- }
- Type boundType = bounds[0];
- if (boundType instanceof Class) {
- List<Object> array = new ArrayList<Object>();
- this.parseArray((Class<?>) boundType, array);
- return array;
- }
- }
- if (actualTypeArgument instanceof ParameterizedType) {
- ParameterizedType parameterizedType = (ParameterizedType) actualTypeArgument;
- List<Object> array = new ArrayList<Object>();
- this.parseArray(parameterizedType, array);
- return array;
- }
- throw new JSONException("TODO : " + collectionType);
- }
- public void acceptType(String typeName) {
- JSONScanner lexer = (JSONScanner) this.lexer;
- lexer.nextTokenWithColon();
- if (lexer.token() != JSONToken.LITERAL_STRING) {
- throw new JSONException("type not match error");
- }
- if (typeName.equals(lexer.stringVal())) {
- lexer.nextToken();
- if (lexer.token() == JSONToken.COMMA) {
- lexer.nextToken();
- }
- } else {
- throw new JSONException("type not match error");
- }
- }
- public int getResolveStatus() {
- return resolveStatus;
- }
- public void setResolveStatus(int resolveStatus) {
- this.resolveStatus = resolveStatus;
- }
- public Object getObject(String path) {
- for (int i = 0; i < contextArrayIndex; ++i) {
- if (path.equals(contextArray[i].getPath())) {
- return contextArray[i].getObject();
- }
- }
- return null;
- }
- @SuppressWarnings("rawtypes")
- public void checkListResolve(Collection array) {
- if (resolveStatus == NeedToResolve) {
- final int index = array.size() - 1;
- final List list = (List) array;
- ResolveTask task = getLastResolveTask();
- task.setFieldDeserializer(new ListResolveFieldDeserializer(this, list, index));
- task.setOwnerContext(context);
- setResolveStatus(DefaultJSONParser.NONE);
- }
- }
- @SuppressWarnings("rawtypes")
- public void checkMapResolve(Map object, String fieldName) {
- if (resolveStatus == NeedToResolve) {
- MapResolveFieldDeserializer fieldResolver = new MapResolveFieldDeserializer(object, fieldName);
- ResolveTask task = getLastResolveTask();
- task.setFieldDeserializer(fieldResolver);
- task.setOwnerContext(context);
- setResolveStatus(DefaultJSONParser.NONE);
- }
- }
- @SuppressWarnings("rawtypes")
- public Object parseObject(final Map object) {
- return parseObject(object, null);
- }
- public JSONObject parseObject() {
- JSONObject object = new JSONObject();
- parseObject(object);
- return object;
- }
- @SuppressWarnings("rawtypes")
- public final void parseArray(final Collection array) {
- parseArray(array, null);
- }
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public final void parseArray(final Collection array, Object fieldName) {
- final JSONLexer lexer = getLexer();
- if (lexer.token() == JSONToken.SET || lexer.token() == JSONToken.TREE_SET) {
- lexer.nextToken();
- }
- if (lexer.token() != JSONToken.LBRACKET) {
- throw new JSONException("syntax error, expect [, actual " + JSONToken.name(lexer.token()));
- }
- lexer.nextToken(JSONToken.LITERAL_STRING);
- ParseContext context = this.getContext();
- this.setContext(array, fieldName);
- try {
- for (int i = 0;; ++i) {
- if (isEnabled(Feature.AllowArbitraryCommas)) {
- while (lexer.token() == JSONToken.COMMA) {
- lexer.nextToken();
- continue;
- }
- }
- Object value;
- switch (lexer.token()) {
- case LITERAL_INT:
- value = lexer.integerValue();
- lexer.nextToken(JSONToken.COMMA);
- break;
- case LITERAL_FLOAT:
- if (lexer.isEnabled(Feature.UseBigDecimal)) {
- value = lexer.decimalValue(true);
- } else {
- value = lexer.decimalValue(false);
- }
- lexer.nextToken(JSONToken.COMMA);
- break;
- case LITERAL_STRING:
- String stringLiteral = lexer.stringVal();
- lexer.nextToken(JSONToken.COMMA);
- if (lexer.isEnabled(Feature.AllowISO8601DateFormat)) {
- JSONScanner iso8601Lexer = new JSONScanner(stringLiteral);
- if (iso8601Lexer.scanISO8601DateIfMatch()) {
- value = iso8601Lexer.getCalendar().getTime();
- } else {
- value = stringLiteral;
- }
- } else {
- value = stringLiteral;
- }
- break;
- case TRUE:
- value = Boolean.TRUE;
- lexer.nextToken(JSONToken.COMMA);
- break;
- case FALSE:
- value = Boolean.FALSE;
- lexer.nextToken(JSONToken.COMMA);
- break;
- case LBRACE:
- JSONObject object = new JSONObject();
- value = parseObject(object, i);
- break;
- case LBRACKET:
- Collection items = new JSONArray();
- parseArray(items, i);
- value = items;
- break;
- case NULL:
- value = null;
- lexer.nextToken(JSONToken.LITERAL_STRING);
- break;
- case RBRACKET:
- lexer.nextToken(JSONToken.COMMA);
- return;
- default:
- value = parse();
- break;
- }
- array.add(value);
- checkListResolve(array);
- if (lexer.token() == JSONToken.COMMA) {
- lexer.nextToken(JSONToken.LITERAL_STRING);
- continue;
- }
- }
- } finally {
- this.setContext(context);
- }
- }
- public ParseContext getContext() {
- return context;
- }
- public List<ResolveTask> getResolveTaskList() {
- return resolveTaskList;
- }
- public void addResolveTask(ResolveTask task) {
- resolveTaskList.add(task);
- }
- public ResolveTask getLastResolveTask() {
- return resolveTaskList.get(resolveTaskList.size() - 1);
- }
- public void setContext(ParseContext context) {
- if (isEnabled(Feature.DisableCircularReferenceDetect)) {
- return;
- }
- this.context = context;
- }
- public void popContext() {
- if (isEnabled(Feature.DisableCircularReferenceDetect)) {
- return;
- }
- this.context = this.context.getParentContext();
- contextArray[contextArrayIndex - 1] = null;
- contextArrayIndex--;
- }
- public ParseContext setContext(Object object, Object fieldName) {
- if (isEnabled(Feature.DisableCircularReferenceDetect)) {
- return null;
- }
- return setContext(this.context, object, fieldName);
- }
- public ParseContext setContext(ParseContext parent, Object object, Object fieldName) {
- if (isEnabled(Feature.DisableCircularReferenceDetect)) {
- return null;
- }
-
- this.context = new ParseContext(parent, object, fieldName);
- addContext(this.context);
- return this.context;
- }
-
- public int getContextLength() {
- return contextArrayIndex;
- }
-
- public void clearContext(ParseContext context, int start) {
- for (int i = start; i < contextArrayIndex; ++i) {
- contextArray[i] = null;
- }
- contextArrayIndex = start;
- this.context = context;
- }
- private void addContext(ParseContext context) {
- int i = contextArrayIndex++;
- if (i >= contextArray.length) {
- int newLen = (contextArray.length * 3) / 2;
- ParseContext[] newArray = new ParseContext[newLen];
- System.arraycopy(contextArray, 0, newArray, 0, contextArray.length);
- contextArray = newArray;
- }
- contextArray[i] = context;
- }
- public Object parse() {
- return parse(null);
- }
- public Object parse(Object fieldName) {
- final JSONLexer lexer = getLexer();
- switch (lexer.token()) {
- case SET:
- lexer.nextToken();
- HashSet<Object> set = new HashSet<Object>();
- parseArray(set, fieldName);
- return set;
- case TREE_SET:
- lexer.nextToken();
- TreeSet<Object> treeSet = new TreeSet<Object>();
- parseArray(treeSet, fieldName);
- return treeSet;
- case LBRACKET:
- JSONArray array = new JSONArray();
- parseArray(array, fieldName);
- return array;
- case LBRACE:
- JSONObject object = new JSONObject();
- return parseObject(object, fieldName);
- case LITERAL_INT:
- Number intValue = lexer.integerValue();
- lexer.nextToken();
- return intValue;
- case LITERAL_FLOAT:
- Object value = lexer.decimalValue(isEnabled(Feature.UseBigDecimal));
- lexer.nextToken();
- return value;
- case LITERAL_STRING:
- String stringLiteral = lexer.stringVal();
- lexer.nextToken(JSONToken.COMMA);
- if (lexer.isEnabled(Feature.AllowISO8601DateFormat)) {
- JSONScanner iso8601Lexer = new JSONScanner(stringLiteral);
- if (iso8601Lexer.scanISO8601DateIfMatch()) {
- return iso8601Lexer.getCalendar().getTime();
- }
- }
- return stringLiteral;
- case NULL:
- lexer.nextToken();
- return null;
- case TRUE:
- lexer.nextToken();
- return Boolean.TRUE;
- case FALSE:
- lexer.nextToken();
- return Boolean.FALSE;
- case NEW:
- lexer.nextToken(JSONToken.IDENTIFIER);
- if (lexer.token() != JSONToken.IDENTIFIER) {
- throw new JSONException("syntax error");
- }
- lexer.nextToken(JSONToken.LPAREN);
- accept(JSONToken.LPAREN);
- long time = ((Number) lexer.integerValue()).longValue();
- accept(JSONToken.LITERAL_INT);
- accept(JSONToken.RPAREN);
- return new Date(time);
- case EOF:
- if (lexer.isBlankInput()) {
- return null;
- }
- throw new JSONException("unterminated json string, pos " + lexer.getBufferPosition());
- case ERROR:
- default:
- throw new JSONException("syntax error, pos " + lexer.getBufferPosition());
- }
- }
- public void config(Feature feature, boolean state) {
- getLexer().config(feature, state);
- }
- public boolean isEnabled(Feature feature) {
- return getLexer().isEnabled(feature);
- }
- public JSONLexer getLexer() {
- return lexer;
- }
- public final void accept(final int token) {
- final JSONLexer lexer = getLexer();
- if (lexer.token() == token) {
- lexer.nextToken();
- } else {
- throw new JSONException("syntax error, expect " + JSONToken.name(token) + ", actual "
- + JSONToken.name(lexer.token()));
- }
- }
- public void close() {
- final JSONLexer lexer = getLexer();
- try {
- if (isEnabled(Feature.AutoCloseSource)) {
- if (!lexer.isEOF()) {
- throw new JSONException("not close json text, token : " + JSONToken.name(lexer.token()));
- }
- }
- } finally {
- lexer.close();
- }
- }
- public static class ResolveTask {
- private final ParseContext context;
- private final String referenceValue;
- private FieldDeserializer fieldDeserializer;
- private ParseContext ownerContext;
- public ResolveTask(ParseContext context, String referenceValue){
- this.context = context;
- this.referenceValue = referenceValue;
- }
- public ParseContext getContext() {
- return context;
- }
- public String getReferenceValue() {
- return referenceValue;
- }
- public FieldDeserializer getFieldDeserializer() {
- return fieldDeserializer;
- }
- public void setFieldDeserializer(FieldDeserializer fieldDeserializer) {
- this.fieldDeserializer = fieldDeserializer;
- }
- public ParseContext getOwnerContext() {
- return ownerContext;
- }
- public void setOwnerContext(ParseContext ownerContext) {
- this.ownerContext = ownerContext;
- }
- }
- }