shade.com.alibaba.fastjson2.JSONReader Maven / Gradle / Ivy
package com.alibaba.fastjson2;
import com.alibaba.fastjson2.filter.ContextAutoTypeBeforeHandler;
import com.alibaba.fastjson2.filter.ExtraProcessor;
import com.alibaba.fastjson2.filter.Filter;
import com.alibaba.fastjson2.reader.*;
import com.alibaba.fastjson2.util.*;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.invoke.*;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import static com.alibaba.fastjson2.JSONFactory.*;
import static com.alibaba.fastjson2.JSONReader.BigIntegerCreator.BIG_INTEGER_CREATOR;
import static com.alibaba.fastjson2.util.JDKUtils.*;
import static com.alibaba.fastjson2.util.TypeUtils.toBigDecimal;
public abstract class JSONReader
implements Closeable {
static final int MAX_EXP = 1023;
static final byte JSON_TYPE_INT = 1;
static final byte JSON_TYPE_DEC = 2;
static final byte JSON_TYPE_STRING = 3;
static final byte JSON_TYPE_BOOL = 4;
static final byte JSON_TYPE_NULL = 5;
static final byte JSON_TYPE_OBJECT = 6;
static final byte JSON_TYPE_ARRAY = 7;
static final byte JSON_TYPE_BIG_DEC = 8;
static final byte JSON_TYPE_INT8 = 9;
static final byte JSON_TYPE_INT16 = 10;
static final byte JSON_TYPE_INT64 = 11;
static final byte JSON_TYPE_FLOAT = 12;
static final byte JSON_TYPE_DOUBLE = 13;
static final char EOI = 0x1A;
static final long SPACE = (1L << ' ') | (1L << '\n') | (1L << '\r') | (1L << '\f') | (1L << '\t') | (1L << '\b');
protected final Context context;
public final boolean jsonb;
public final boolean utf8;
List resolveTasks;
protected int offset;
protected char ch;
protected boolean comma;
protected boolean nameEscape;
protected boolean valueEscape;
protected boolean wasNull;
protected boolean boolValue;
protected boolean negative;
protected byte valueType;
protected short exponent;
protected short scale;
protected int mag0;
protected int mag1;
protected int mag2;
protected int mag3;
protected int level;
protected String stringValue;
protected Object complex; // Map | List
protected boolean typeRedirect; // redirect for {"@type":"xxx"",...
protected char[] doubleChars;
public final char current() {
return ch;
}
public boolean isEnd() {
return ch == EOI;
}
public byte getType() {
return -128;
}
public boolean isInt() {
return ch == '-' || ch == '+' || (ch >= '0' && ch <= '9');
}
public abstract boolean isNull();
public final boolean hasComma() {
return comma;
}
public abstract Date readNullOrNewDate();
public abstract boolean nextIfNull();
public JSONReader(Context context, boolean jsonb, boolean utf8) {
this.context = context;
this.jsonb = jsonb;
this.utf8 = utf8;
}
public final Context getContext() {
return context;
}
public final void errorOnNoneSerializable(Class objectClass) {
if ((context.features & Feature.ErrorOnNoneSerializable.mask) != 0
&& !Serializable.class.isAssignableFrom(objectClass)) {
throw new JSONException("not support none-Serializable, class " + objectClass.getName());
}
}
public final boolean isEnabled(Feature feature) {
return (context.features & feature.mask) != 0;
}
public final Locale getLocale() {
return context.getLocale();
}
public final ZoneId getZoneId() {
return context.getZoneId();
}
public final long features(long features) {
return context.features | features;
}
public int getRawInt() {
return 0;
}
public long getRawLong() {
return 0;
}
public boolean nextIfName4Match2() {
return false;
}
public boolean nextIfValue4Match2() {
return false;
}
public boolean nextIfName4Match3() {
return false;
}
public boolean nextIfValue4Match3() {
return false;
}
public boolean nextIfName4Match4(byte c4) {
return false;
}
public boolean nextIfValue4Match4(byte c4) {
return false;
}
public boolean nextIfName4Match5(int name1) {
return false;
}
public boolean nextIfValue4Match5(byte c4, byte c5) {
return false;
}
public boolean nextIfName4Match6(int name1) {
return false;
}
public boolean nextIfValue4Match6(int name1) {
return false;
}
public boolean nextIfName4Match7(int name1) {
return false;
}
public boolean nextIfValue4Match7(int name1) {
return false;
}
public boolean nextIfName4Match8(int name1, byte c8) {
return false;
}
public boolean nextIfValue4Match8(int name1, byte c8) {
return false;
}
public boolean nextIfName4Match9(long name1) {
return false;
}
public boolean nextIfValue4Match9(int name1, byte c8, byte c9) {
return false;
}
public boolean nextIfName4Match10(long name1) {
return false;
}
public boolean nextIfValue4Match10(long name1) {
return false;
}
public boolean nextIfName4Match11(long name1) {
return false;
}
public boolean nextIfValue4Match11(long name1) {
return false;
}
public boolean nextIfName4Match12(long name1, byte c12) {
return false;
}
public boolean nextIfName4Match13(long name1, int name2) {
return false;
}
public boolean nextIfName4Match14(long name1, int name2) {
return false;
}
public boolean nextIfName4Match15(long name1, int name2) {
return false;
}
public boolean nextIfName4Match16(long name1, int name2, byte c16) {
return false;
}
public boolean nextIfName4Match17(long name1, long name2) {
return false;
}
public boolean nextIfName4Match18(long name1, long name2) {
return false;
}
public boolean nextIfName4Match19(long name1, long name2) {
return false;
}
public boolean nextIfName4Match20(long name1, long name2, byte c20) {
return false;
}
public boolean nextIfName4Match21(long name1, long name2, int name3) {
return false;
}
public boolean nextIfName4Match22(long name1, long name2, int name3) {
return false;
}
public boolean nextIfName4Match23(long name1, long name2, int name3) {
return false;
}
public boolean nextIfName4Match24(long name1, long name2, int name3, byte c24) {
return false;
}
public boolean nextIfName4Match25(long name1, long name2, long name3) {
return false;
}
public boolean nextIfName4Match26(long name1, long name2, long name3) {
return false;
}
public boolean nextIfName4Match27(long name1, long name2, long name3) {
return false;
}
public boolean nextIfName4Match28(long name1, long name2, long name3, byte c28) {
return false;
}
public boolean nextIfName4Match29(long name1, long name2, long name3, int name4) {
return false;
}
public boolean nextIfName4Match30(long name1, long name2, long name3, int name4) {
return false;
}
public boolean nextIfName4Match31(long name1, long name2, long name3, int name4) {
return false;
}
public boolean nextIfName4Match32(long name1, long name2, long name3, int name4, byte c32) {
return false;
}
public boolean nextIfName4Match33(long name1, long name2, long name3, long name4) {
return false;
}
public boolean nextIfName4Match34(long name1, long name2, long name3, long name4) {
return false;
}
public boolean nextIfName4Match35(long name1, long name2, long name3, long name4) {
return false;
}
public boolean nextIfName4Match36(long name1, long name2, long name3, long name4, byte c35) {
return false;
}
public boolean nextIfName4Match37(long name1, long name2, long name3, long name4, int name5) {
return false;
}
public boolean nextIfName4Match38(long name1, long name2, long name3, long name4, int name5) {
return false;
}
public boolean nextIfName4Match39(long name1, long name2, long name3, long name4, int name5) {
return false;
}
public boolean nextIfName4Match40(long name1, long name2, long name3, long name4, int name5, byte c40) {
return false;
}
public boolean nextIfName4Match41(long name1, long name2, long name3, long name4, long name5) {
return false;
}
public boolean nextIfName4Match42(long name1, long name2, long name3, long name4, long name5) {
return false;
}
public boolean nextIfName4Match43(long name1, long name2, long name3, long name4, long name5) {
return false;
}
public boolean nextIfName8Match0() {
return false;
}
public boolean nextIfName8Match1() {
return false;
}
public boolean nextIfName8Match2() {
return false;
}
public final void handleResolveTasks(Object root) {
if (resolveTasks == null) {
return;
}
Object previous = null;
for (ResolveTask resolveTask : resolveTasks) {
JSONPath path = resolveTask.reference;
FieldReader fieldReader = resolveTask.fieldReader;
Object fieldValue;
if (path.isPrevious()) {
fieldValue = previous;
} else {
if (!path.isRef()) {
throw new JSONException("reference path invalid : " + path);
}
path.setReaderContext(context);
if ((context.features & Feature.FieldBased.mask) != 0) {
JSONWriter.Context writeContext = JSONFactory.createWriteContext();
writeContext.features |= JSONWriter.Feature.FieldBased.mask;
path.setWriterContext(writeContext);
}
fieldValue = path.eval(root);
previous = fieldValue;
}
Object resolvedName = resolveTask.name;
Object resolvedObject = resolveTask.object;
if (resolvedName != null) {
if (resolvedObject instanceof Map) {
Map map = (Map) resolvedObject;
if (resolvedName instanceof ReferenceKey) {
if (map instanceof LinkedHashMap) {
int size = map.size();
if (size == 0) {
continue;
}
Object[] keys = new Object[size];
Object[] values = new Object[size];
int index = 0;
for (Object o : map.entrySet()) {
Map.Entry entry = (Map.Entry) o;
Object entryKey = entry.getKey();
if (resolvedName == entryKey) {
keys[index] = fieldValue;
} else {
keys[index] = entryKey;
}
values[index++] = entry.getValue();
}
map.clear();
for (int j = 0; j < keys.length; j++) {
map.put(keys[j], values[j]);
}
} else {
map.put(fieldValue, map.remove(resolvedName));
}
} else {
map.put(resolvedName, fieldValue);
}
continue;
}
if (resolvedName instanceof Integer) {
if (resolvedObject instanceof List) {
int index = (Integer) resolvedName;
List list = (List) resolvedObject;
if (index == list.size()) {
list.add(fieldValue);
} else {
if (index < list.size() && list.get(index) == null) {
list.set(index, fieldValue);
} else {
list.add(index, fieldValue);
}
}
continue;
}
if (resolvedObject instanceof Object[]) {
int index = (Integer) resolvedName;
Object[] array = (Object[]) resolvedObject;
array[index] = fieldValue;
continue;
}
if (resolvedObject instanceof Collection) {
Collection collection = (Collection) resolvedObject;
collection.add(fieldValue);
continue;
}
}
}
fieldReader.accept(resolvedObject, fieldValue);
}
}
public final ObjectReader getObjectReader(Type type) {
boolean fieldBased = (context.features & JSONReader.Feature.FieldBased.mask) != 0;
return context.provider.getObjectReader(type, fieldBased);
}
public final boolean isSupportSmartMatch() {
return (context.features & Feature.SupportSmartMatch.mask) != 0;
}
public final boolean isInitStringFieldAsEmpty() {
return (context.features & Feature.InitStringFieldAsEmpty.mask) != 0;
}
public final boolean isSupportSmartMatch(long features) {
return ((context.features | features) & Feature.SupportSmartMatch.mask) != 0;
}
public final boolean isSupportBeanArray() {
return (context.features & Feature.SupportArrayToBean.mask) != 0;
}
public final boolean isSupportBeanArray(long features) {
return ((context.features | features) & Feature.SupportArrayToBean.mask) != 0;
}
public final boolean isSupportAutoType(long features) {
return ((context.features | features) & Feature.SupportAutoType.mask) != 0;
}
public final boolean isSupportAutoTypeOrHandler(long features) {
return ((context.features | features) & Feature.SupportAutoType.mask) != 0 || context.autoTypeBeforeHandler != null;
}
public final boolean isJSONB() {
return jsonb;
}
public final boolean isIgnoreNoneSerializable() {
return (context.features & Feature.IgnoreNoneSerializable.mask) != 0;
}
public ObjectReader checkAutoType(Class expectClass, long expectClassHash, long features) {
return null;
}
final char char1(int c) {
switch (c) {
case '0':
return '\0';
case '1':
return '\1';
case '2':
return '\2';
case '3':
return '\3';
case '4':
return '\4';
case '5':
return '\5';
case '6':
return '\6';
case '7':
return '\7';
case 'b': // 8
return '\b';
case 't': // 9
return '\t';
case 'n': // 10
return '\n';
case 'v': // 11
return '\u000B';
case 'f': // 12
case 'F':
return '\f';
case 'r': // 13
return '\r';
case '"': // 34
case '\'': // 39
case '/': // 47
case '.': // 47
case '\\': // 92
case '#':
case '&':
case '[':
case ']':
case '@':
case '(':
case ')':
case '_':
case ',':
return (char) c;
default:
throw new JSONException(info("unclosed.str '\\" + (char) c));
}
}
static char char2(int c1, int c2) {
return (char) (DIGITS2[c1] * 0x10
+ DIGITS2[c2]);
}
static char char4(int c1, int c2, int c3, int c4) {
return (char) (DIGITS2[c1] * 0x1000
+ DIGITS2[c2] * 0x100
+ DIGITS2[c3] * 0x10
+ DIGITS2[c4]);
}
public abstract boolean nextIfObjectStart();
public abstract boolean nextIfNullOrEmptyString();
public abstract boolean nextIfObjectEnd();
public int startArray() {
if (!nextIfArrayStart()) {
throw new JSONException(info("illegal input, expect '[', but " + ch));
}
return Integer.MAX_VALUE;
}
public abstract boolean isReference();
public abstract String readReference();
public boolean readReference(List list, int i) {
if (!isReference()) {
return false;
}
String path = readReference();
if ("..".equals(path)) {
list.add(list);
} else {
addResolveTask(list, i, JSONPath.of(path));
}
return true;
}
public final void addResolveTask(FieldReader fieldReader, Object object, JSONPath path) {
if (resolveTasks == null) {
resolveTasks = new ArrayList<>();
}
resolveTasks.add(new ResolveTask(fieldReader, object, fieldReader.fieldName, path));
}
public final void addResolveTask(Map object, Object key, JSONPath reference) {
if (resolveTasks == null) {
resolveTasks = new ArrayList<>();
}
if (object instanceof LinkedHashMap) {
object.put(key, null);
}
resolveTasks.add(new ResolveTask(null, object, key, reference));
}
public final void addResolveTask(Collection object, int i, JSONPath reference) {
if (resolveTasks == null) {
resolveTasks = new ArrayList<>();
}
resolveTasks.add(new ResolveTask(null, object, i, reference));
}
public final void addResolveTask(Object[] object, int i, JSONPath reference) {
if (resolveTasks == null) {
resolveTasks = new ArrayList<>();
}
resolveTasks.add(new ResolveTask(null, object, i, reference));
}
public boolean isArray() {
return this.ch == '[';
}
public boolean isObject() {
return this.ch == '{';
}
public boolean isNumber() {
switch (this.ch) {
case '-':
case '+':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return true;
default:
return false;
}
}
public boolean isString() {
return this.ch == '"' || this.ch == '\'';
}
public void endArray() {
next();
}
public abstract boolean nextIfMatch(char ch);
public abstract boolean nextIfComma();
public abstract boolean nextIfArrayStart();
public abstract boolean nextIfArrayEnd();
public abstract boolean nextIfSet();
public abstract boolean nextIfInfinity();
public abstract String readPattern();
public final int getOffset() {
return offset;
}
public abstract void next();
public abstract long readValueHashCode();
public long readTypeHashCode() {
return readValueHashCode();
}
public abstract long readFieldNameHashCode();
public abstract long getNameHashCodeLCase();
public abstract String readFieldName();
public abstract String getFieldName();
public final void setTypeRedirect(boolean typeRedirect) {
this.typeRedirect = typeRedirect;
}
public final boolean isTypeRedirect() {
return typeRedirect;
}
public abstract long readFieldNameHashCodeUnquote();
public final String readFieldNameUnquote() {
readFieldNameHashCodeUnquote();
return getFieldName();
}
public abstract boolean skipName();
public abstract void skipValue();
public boolean isBinary() {
return false;
}
public abstract byte[] readHex();
public byte[] readBinary() {
if (ch == 'x') {
return readHex();
}
if (isString()) {
String str = readString();
if (str.isEmpty()) {
return null;
}
if ((context.features & Feature.Base64StringAsByteArray.mask) != 0) {
return Base64.getDecoder().decode(str);
}
throw new JSONException(info("not support input " + str));
}
if (nextIfArrayStart()) {
int index = 0;
byte[] bytes = new byte[64];
while (true) {
if (ch == ']') {
next();
break;
}
if (index == bytes.length) {
int oldCapacity = bytes.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
bytes = Arrays.copyOf(bytes, newCapacity);
}
bytes[index++] = (byte) readInt32Value();
}
nextIfComma();
return Arrays.copyOf(bytes, index);
}
throw new JSONException(info("not support read binary"));
}
public abstract int readInt32Value();
public int[] readInt32ValueArray() {
if (nextIfNull()) {
return null;
}
if (nextIfArrayStart()) {
int[] values = new int[8];
int size = 0;
while (!nextIfArrayEnd()) {
if (isEnd()) {
throw new JSONException(info("input end"));
}
if (size == values.length) {
values = Arrays.copyOf(values, values.length << 1);
}
values[size++] = readInt32Value();
}
nextIfComma();
int[] array;
if (size == values.length) {
array = values;
} else {
array = Arrays.copyOf(values, size);
}
return array;
}
if (isString()) {
String str = readString();
if (str.isEmpty()) {
return null;
}
throw new JSONException(info("not support input " + str));
}
throw new JSONException(info("TODO"));
}
public boolean nextIfMatch(byte type) {
throw new JSONException("UnsupportedOperation");
}
public boolean nextIfMatchTypedAny() {
throw new JSONException("UnsupportedOperation");
}
public abstract boolean nextIfMatchIdent(char c0, char c1, char c2);
public abstract boolean nextIfMatchIdent(char c0, char c1, char c2, char c3);
public abstract boolean nextIfMatchIdent(char c0, char c1, char c2, char c3, char c4);
public abstract boolean nextIfMatchIdent(char c0, char c1, char c2, char c3, char c4, char c5);
public final Byte readInt8() {
Integer i = readInt32();
if (i == null) {
return null;
}
return i.byteValue();
}
public byte readInt8Value() {
int i = readInt32Value();
return (byte) i;
}
public final Short readInt16() {
Integer i = readInt32();
if (i == null) {
return null;
}
return i.shortValue();
}
public short readInt16Value() {
int i = readInt32Value();
return (short) i;
}
public abstract Integer readInt32();
public final int getInt32Value() {
switch (valueType) {
case JSON_TYPE_INT:
if (mag1 == 0 && mag2 == 0 && mag3 != Integer.MIN_VALUE) {
return negative ? -mag3 : mag3;
}
Number number = getNumber();
if (number instanceof Long) {
long longValue = number.longValue();
if (longValue < Integer.MIN_VALUE || longValue > Integer.MAX_VALUE) {
throw new JSONException(info("integer overflow " + longValue));
}
return (int) longValue;
}
return number.intValue();
case JSON_TYPE_DEC:
return getNumber().intValue();
case JSON_TYPE_BOOL:
return boolValue ? 1 : 0;
case JSON_TYPE_NULL:
if ((context.features & Feature.ErrorOnNullForPrimitives.mask) != 0) {
throw new JSONException(info("int value not support input null"));
}
return 0;
case JSON_TYPE_STRING: {
return toInt32(stringValue);
}
case JSON_TYPE_OBJECT: {
Number num = toNumber((Map) complex);
if (num != null) {
return num.intValue();
}
return 0;
}
case JSON_TYPE_ARRAY: {
return toInt((List) complex);
}
default:
throw new JSONException("TODO : " + valueType);
}
}
public final long getInt64Value() {
switch (valueType) {
case JSON_TYPE_INT:
if (mag1 == 0 && mag2 == 0 && mag3 != Integer.MIN_VALUE) {
return negative ? -mag3 : mag3;
}
return getNumber().longValue();
case JSON_TYPE_DEC:
return getNumber().longValue();
case JSON_TYPE_BOOL:
return boolValue ? 1 : 0;
case JSON_TYPE_NULL:
if ((context.features & Feature.ErrorOnNullForPrimitives.mask) != 0) {
throw new JSONException(info("long value not support input null"));
}
return 0;
case JSON_TYPE_STRING: {
return toInt64(stringValue);
}
case JSON_TYPE_OBJECT: {
return toLong((Map) complex);
}
case JSON_TYPE_ARRAY: {
return toInt((List) complex);
}
default:
throw new JSONException("TODO");
}
}
protected final Long getInt64() {
switch (valueType) {
case JSON_TYPE_INT:
if (mag1 == 0 && mag2 == 0 && mag3 != Integer.MIN_VALUE) {
return (long) (negative ? -mag3 : mag3);
}
int[] mag;
if (mag0 == 0) {
if (mag1 == 0) {
if (mag2 == Integer.MIN_VALUE && mag3 == 0 && !negative) {
return Long.MIN_VALUE;
}
long v3 = mag3 & 0XFFFFFFFFL;
long v2 = mag2 & 0XFFFFFFFFL;
if (v2 <= Integer.MAX_VALUE) {
long v23 = (v2 << 32) + (v3);
return negative ? -v23 : v23;
}
mag = new int[]{mag2, mag3};
} else {
mag = new int[]{mag1, mag2, mag3};
}
} else {
mag = new int[]{mag0, mag1, mag2, mag3};
}
int signum = negative ? -1 : 1;
BigInteger bigInt = BIG_INTEGER_CREATOR.apply(signum, mag);
return bigInt.longValue();
case JSON_TYPE_DEC:
return getNumber().longValue();
case JSON_TYPE_BOOL:
return (long) (boolValue ? 1 : 0);
case JSON_TYPE_NULL:
return null;
case JSON_TYPE_STRING: {
return toInt64(stringValue);
}
case JSON_TYPE_OBJECT: {
Number num = toNumber((Map) complex);
if (num != null) {
return num.longValue();
}
return null;
}
default:
throw new JSONException("TODO");
}
}
public long[] readInt64ValueArray() {
if (nextIfNull()) {
return null;
}
if (nextIfArrayStart()) {
long[] values = new long[8];
int size = 0;
while (!nextIfArrayEnd()) {
if (isEnd()) {
throw new JSONException(info("input end"));
}
if (size == values.length) {
values = Arrays.copyOf(values, values.length << 1);
}
values[size++] = readInt64Value();
}
nextIfComma();
long[] array;
if (size == values.length) {
array = values;
} else {
array = Arrays.copyOf(values, size);
}
return array;
}
if (isString()) {
String str = readString();
if (str.isEmpty()) {
return null;
}
throw new JSONException(info("not support input " + str));
}
throw new JSONException(info("TODO"));
}
public abstract long readInt64Value();
public abstract Long readInt64();
public abstract float readFloatValue();
public Float readFloat() {
if (nextIfNull()) {
return null;
}
wasNull = false;
float value = readFloatValue();
if (wasNull) {
return null;
}
return value;
}
public abstract double readDoubleValue();
public final Double readDouble() {
if (nextIfNull()) {
return null;
}
wasNull = false;
double value = readDoubleValue();
if (wasNull) {
return null;
}
return value;
}
public Number readNumber() {
readNumber0();
return getNumber();
}
public BigInteger readBigInteger() {
readNumber0();
return getBigInteger();
}
public abstract BigDecimal readBigDecimal();
public abstract UUID readUUID();
public final boolean isLocalDate() {
if (!isString()) {
return false;
}
LocalDate localDate;
int len = getStringLength();
switch (len) {
case 8:
localDate = readLocalDate8();
break;
case 9:
localDate = readLocalDate9();
break;
case 10:
localDate = readLocalDate10();
break;
case 11:
localDate = readLocalDate11();
break;
default:
return false;
}
return localDate != null;
}
public LocalDate readLocalDate() {
if (nextIfNull()) {
return null;
}
if (isInt()) {
long millis = readInt64Value();
if (context.formatUnixTime) {
millis *= 1000L;
}
Instant instant = Instant.ofEpochMilli(millis);
ZonedDateTime zdt = instant.atZone(context.getZoneId());
return zdt.toLocalDate();
}
if (context.dateFormat == null
|| context.formatyyyyMMddhhmmss19
|| context.formatyyyyMMddhhmmssT19
|| context.formatyyyyMMdd8
|| context.formatISO8601) {
int len = getStringLength();
LocalDateTime ldt = null;
LocalDate localDate;
switch (len) {
case 8:
localDate = readLocalDate8();
ldt = localDate == null ? null : LocalDateTime.of(localDate, LocalTime.MIN);
break;
case 9:
localDate = readLocalDate9();
ldt = localDate == null ? null : LocalDateTime.of(localDate, LocalTime.MIN);
break;
case 10:
localDate = readLocalDate10();
ldt = localDate == null ? null : LocalDateTime.of(localDate, LocalTime.MIN);
break;
case 11:
localDate = readLocalDate11();
ldt = localDate == null ? null : LocalDateTime.of(localDate, LocalTime.MIN);
break;
case 19:
ldt = readLocalDateTime19();
break;
case 20:
ldt = readLocalDateTime20();
break;
default:
if (len > 20) {
ldt = readLocalDateTimeX(len);
}
break;
}
if (ldt != null) {
return ldt.toLocalDate();
}
}
String str = readString();
if (str.isEmpty() || "null".equals(str)) {
return null;
}
DateTimeFormatter formatter = context.getDateFormatter();
if (formatter != null) {
if (context.formatHasHour) {
return LocalDateTime
.parse(str, formatter)
.toLocalDate();
}
return LocalDate.parse(str, formatter);
}
if (IOUtils.isNumber(str)) {
long millis = Long.parseLong(str);
Instant instant = Instant.ofEpochMilli(millis);
ZonedDateTime zdt = instant.atZone(context.getZoneId());
return zdt.toLocalDate();
}
throw new JSONException("not support input : " + str);
}
public final boolean isLocalDateTime() {
if (!isString()) {
return false;
}
int len = getStringLength();
switch (len) {
case 16:
return readLocalDateTime16() != null;
case 17:
return readLocalDateTime17() != null;
case 18:
return readLocalDateTime18() != null;
case 19:
return readLocalDateTime19() != null;
case 20:
return readLocalDateTime20() != null;
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
case 27:
case 28:
case 29:
return readLocalDateTimeX(len) != null;
default:
break;
}
return false;
}
public LocalDateTime readLocalDateTime() {
if (isInt()) {
long millis = readInt64Value();
Instant instant = Instant.ofEpochMilli(millis);
ZonedDateTime zdt = instant.atZone(context.getZoneId());
return zdt.toLocalDateTime();
}
if (context.dateFormat == null
|| context.formatyyyyMMddhhmmss19
|| context.formatyyyyMMddhhmmssT19
|| context.formatyyyyMMdd8
|| context.formatISO8601) {
int len = getStringLength();
LocalDate localDate;
switch (len) {
case 8:
localDate = readLocalDate8();
return localDate == null ? null : LocalDateTime.of(localDate, LocalTime.MIN);
case 9:
localDate = readLocalDate9();
return localDate == null ? null : LocalDateTime.of(localDate, LocalTime.MIN);
case 10:
localDate = readLocalDate10();
return localDate == null ? null : LocalDateTime.of(localDate, LocalTime.MIN);
case 11:
localDate = readLocalDate11();
return localDate == null ? null : LocalDateTime.of(localDate, LocalTime.MIN);
case 16:
return readLocalDateTime16();
case 17: {
LocalDateTime ldt = readLocalDateTime17();
if (ldt != null) {
return ldt;
}
break;
}
case 18: {
LocalDateTime ldt = readLocalDateTime18();
if (ldt != null) {
return ldt;
}
break;
}
case 19: {
LocalDateTime ldt = readLocalDateTime19();
if (ldt != null) {
return ldt;
}
break;
}
case 20: {
LocalDateTime ldt = readLocalDateTime20();
if (ldt != null) {
return ldt;
}
ZonedDateTime zdt = readZonedDateTimeX(len);
if (zdt != null) {
return zdt.toLocalDateTime();
}
break;
}
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
case 27:
case 28:
case 29:
LocalDateTime ldt = readLocalDateTimeX(len);
if (ldt != null) {
return ldt;
}
ZonedDateTime zdt = readZonedDateTimeX(len);
if (zdt != null) {
ZoneId contextZoneId = context.getZoneId();
if (!zdt.getZone().equals(contextZoneId)) {
ldt = zdt.toInstant().atZone(contextZoneId).toLocalDateTime();
} else {
ldt = zdt.toLocalDateTime();
}
return ldt;
}
break;
default:
break;
}
}
String str = readString();
if (str.isEmpty() || "null".equals(str)) {
wasNull = true;
return null;
}
DateTimeFormatter formatter = context.getDateFormatter();
if (formatter != null) {
if (!context.formatHasHour) {
return LocalDateTime.of(
LocalDate.parse(str, formatter),
LocalTime.MIN
);
}
return LocalDateTime.parse(str, formatter);
}
if (IOUtils.isNumber(str)) {
long millis = Long.parseLong(str);
if (context.formatUnixTime) {
millis *= 1000L;
}
Instant instant = Instant.ofEpochMilli(millis);
return LocalDateTime.ofInstant(instant, context.getZoneId());
}
if (str.startsWith("/Date(") && str.endsWith(")/")) {
String dotnetDateStr = str.substring(6, str.length() - 2);
int i = dotnetDateStr.indexOf('+');
if (i == -1) {
i = dotnetDateStr.indexOf('-');
}
if (i != -1) {
dotnetDateStr = dotnetDateStr.substring(0, i);
}
long millis = Long.parseLong(dotnetDateStr);
Instant instant = Instant.ofEpochMilli(millis);
return LocalDateTime.ofInstant(instant, context.getZoneId());
}
if ("0000-00-00 00:00:00".equals(str)) {
wasNull = true;
return null;
}
throw new JSONException(info("read LocalDateTime error " + str));
}
public abstract OffsetDateTime readOffsetDateTime();
public ZonedDateTime readZonedDateTime() {
if (isInt()) {
long millis = readInt64Value();
if (context.formatUnixTime) {
millis *= 1000L;
}
Instant instant = Instant.ofEpochMilli(millis);
return instant.atZone(context.getZoneId());
}
if (isString()) {
if (context.dateFormat == null
|| context.formatyyyyMMddhhmmss19
|| context.formatyyyyMMddhhmmssT19
|| context.formatyyyyMMdd8
|| context.formatISO8601) {
int len = getStringLength();
LocalDateTime ldt = null;
LocalDate localDate;
switch (len) {
case 8:
localDate = readLocalDate8();
ldt = localDate == null ? null : LocalDateTime.of(localDate, LocalTime.MIN);
break;
case 9:
localDate = readLocalDate9();
ldt = localDate == null ? null : LocalDateTime.of(localDate, LocalTime.MIN);
break;
case 10:
localDate = readLocalDate10();
ldt = localDate == null ? null : LocalDateTime.of(localDate, LocalTime.MIN);
break;
case 11:
localDate = readLocalDate11();
ldt = LocalDateTime.of(localDate, LocalTime.MIN);
break;
case 16:
ldt = readLocalDateTime16();
break;
case 17:
ldt = readLocalDateTime17();
break;
case 18:
ldt = readLocalDateTime18();
break;
case 19:
ldt = readLocalDateTime19();
break;
case 20: {
ldt = readLocalDateTime20();
break;
}
default:
ZonedDateTime zdt = readZonedDateTimeX(len);
if (zdt != null) {
return zdt;
}
break;
}
if (ldt != null) {
return ZonedDateTime.ofLocal(
ldt,
context.getZoneId(),
null
);
}
}
String str = readString();
if (str.isEmpty() || "null".equals(str)) {
return null;
}
DateTimeFormatter formatter = context.getDateFormatter();
if (formatter != null) {
if (!context.formatHasHour) {
LocalDate localDate = LocalDate.parse(str, formatter);
return ZonedDateTime.of(localDate, LocalTime.MIN, context.getZoneId());
}
LocalDateTime localDateTime = LocalDateTime.parse(str, formatter);
return ZonedDateTime.of(localDateTime, context.getZoneId());
}
if (IOUtils.isNumber(str)) {
long millis = Long.parseLong(str);
if (context.formatUnixTime) {
millis *= 1000L;
}
Instant instant = Instant.ofEpochMilli(millis);
return instant.atZone(context.getZoneId());
}
return ZonedDateTime.parse(str);
}
if (nextIfNull()) {
return null;
}
throw new JSONException("TODO : " + ch);
}
public OffsetTime readOffsetTime() {
throw new JSONException("TODO");
}
public Calendar readCalendar() {
if (isString()) {
long millis = readMillisFromString();
if (millis == 0 && wasNull) {
return null;
}
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(millis);
return calendar;
}
if (readIfNull()) {
return null;
}
long millis = readInt64Value();
if (context.formatUnixTime) {
millis *= 1000;
}
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(millis);
return calendar;
}
public Date readDate() {
if (isInt()) {
long millis = readInt64Value();
return new Date(millis);
}
if (readIfNull()) {
return null;
}
if (nextIfNullOrEmptyString()) {
return null;
}
long millis;
if (isTypeRedirect() && nextIfMatchIdent('"', 'v', 'a', 'l', '"')) {
nextIfMatch(':');
millis = readInt64Value();
nextIfObjectEnd();
setTypeRedirect(false);
} else {
millis = readMillisFromString();
}
if (millis == 0 && wasNull) {
return null;
}
return new Date(millis);
}
public LocalTime readLocalTime() {
if (nextIfNull()) {
return null;
}
if (isInt()) {
long millis = readInt64Value();
Instant instant = Instant.ofEpochMilli(millis);
ZonedDateTime zdt = instant.atZone(context.getZoneId());
return zdt.toLocalTime();
}
int len = getStringLength();
switch (len) {
case 5:
return readLocalTime5();
case 8:
return readLocalTime8();
case 9:
return readLocalTime9();
case 10:
return readLocalTime10();
case 11:
return readLocalTime11();
case 12:
return readLocalTime12();
case 18:
return readLocalTime18();
case 19:
return readLocalDateTime19()
.toLocalTime();
case 20:
return readLocalDateTime20()
.toLocalTime();
default:
break;
}
String str = readString();
if (str.isEmpty() || "null".equals(str)) {
return null;
}
if (IOUtils.isNumber(str)) {
long millis = Long.parseLong(str);
Instant instant = Instant.ofEpochMilli(millis);
ZonedDateTime zdt = instant.atZone(context.getZoneId());
return zdt.toLocalTime();
}
throw new JSONException("not support len : " + str);
}
protected abstract int getStringLength();
public Instant readInstant() {
if (nextIfNull()) {
return null;
}
if (isNumber()) {
long millis = readInt64Value();
if (context.formatUnixTime) {
millis *= 1000L;
}
return Instant.ofEpochMilli(millis);
}
if (isObject()) {
return (Instant) getObjectReader(Instant.class)
.createInstance(
readObject(),
0L
);
}
ZonedDateTime zdt = readZonedDateTime();
if (zdt == null) {
return null;
}
return Instant.ofEpochSecond(
zdt.toEpochSecond(),
zdt.toLocalTime().getNano());
}
public final long readMillisFromString() {
wasNull = false;
String format = context.dateFormat;
if (format == null
|| context.formatyyyyMMddhhmmss19
|| context.formatyyyyMMddhhmmssT19
|| context.formatyyyyMMdd8
|| context.formatISO8601) {
int len = getStringLength();
LocalDateTime ldt = null;
LocalDate localDate;
switch (len) {
case 8: {
localDate = readLocalDate8();
if (localDate == null) {
throw new JSONException("TODO : " + readString());
}
ldt = LocalDateTime.of(localDate, LocalTime.MIN);
break;
}
case 9: {
localDate = readLocalDate9();
if (localDate != null) {
ldt = LocalDateTime.of(localDate, LocalTime.MIN);
}
break;
}
case 10: {
localDate = readLocalDate10();
if (localDate == null) {
String str = readString();
if ("0000-00-00".equals(str)) {
wasNull = true;
return 0;
}
if (IOUtils.isNumber(str)) {
return Long.parseLong(str);
}
throw new JSONException("TODO : " + str);
} else {
ldt = LocalDateTime.of(localDate, LocalTime.MIN);
}
break;
}
case 11: {
localDate = readLocalDate11();
if (localDate != null) {
ldt = LocalDateTime.of(localDate, LocalTime.MIN);
}
break;
}
case 12: {
ldt = readLocalDateTime12();
break;
}
case 14: {
ldt = readLocalDateTime14();
break;
}
case 16: {
ldt = readLocalDateTime16();
break;
}
case 17: {
ldt = readLocalDateTime17();
break;
}
case 18: {
ldt = readLocalDateTime18();
break;
}
case 19: {
long millis = readMillis19();
if (millis != 0 || !wasNull) {
return millis;
}
ldt = readLocalDateTime19();
break;
}
case 20: {
ldt = readLocalDateTime20();
break;
}
default:
break;
}
ZonedDateTime zdt = null;
if (ldt != null) {
zdt = ZonedDateTime.ofLocal(ldt, context.getZoneId(), null);
} else if (len >= 20) {
zdt = readZonedDateTimeX(len);
if (zdt == null && (len >= 32 && len <= 35)) {
String str = readString();
zdt = DateUtils.parseZonedDateTime(str, null);
}
}
if (zdt != null) {
long seconds = zdt.toEpochSecond();
int nanos = zdt.toLocalTime().getNano();
if (seconds < 0 && nanos > 0) {
long millis = (seconds + 1) * 1000;
long adjustment = nanos / 1000_000 - 1000;
return millis + adjustment;
} else {
long millis = seconds * 1000L;
return millis + nanos / 1000_000;
}
}
}
String str = readString();
if (str.isEmpty() || "null".equals(str)) {
wasNull = true;
return 0;
}
if (context.formatMillis || context.formatUnixTime) {
long millis = Long.parseLong(str);
if (context.formatUnixTime) {
millis *= 1000L;
}
return millis;
}
if (format != null && !format.isEmpty()) {
if ("yyyy-MM-dd HH:mm:ss".equals(format)) {
if ((str.length() < 4 || str.charAt(4) != '-') && IOUtils.isNumber(str)) {
return Long.parseLong(str);
}
return DateUtils.parseMillis19(str, null);
}
SimpleDateFormat utilFormat = new SimpleDateFormat(format);
try {
return utilFormat
.parse(str)
.getTime();
} catch (ParseException e) {
throw new JSONException("parse date error, " + str + ", expect format " + utilFormat.toPattern());
}
}
if ("0000-00-00T00:00:00".equals(str)
|| "0001-01-01T00:00:00+08:00".equals(str)) {
return 0;
}
if (str.startsWith("/Date(") && str.endsWith(")/")) {
String dotnetDateStr = str.substring(6, str.length() - 2);
int i = dotnetDateStr.indexOf('+');
if (i == -1) {
i = dotnetDateStr.indexOf('-');
}
if (i != -1) {
dotnetDateStr = dotnetDateStr.substring(0, i);
}
return Long.parseLong(dotnetDateStr);
} else if (IOUtils.isNumber(str)) {
return Long.parseLong(str);
}
throw new JSONException(info("format " + format + " not support, input " + str));
}
protected abstract LocalDateTime readLocalDateTime12();
protected abstract LocalDateTime readLocalDateTime14();
protected abstract LocalDateTime readLocalDateTime16();
protected abstract LocalDateTime readLocalDateTime17();
protected abstract LocalDateTime readLocalDateTime18();
protected abstract LocalDateTime readLocalDateTime19();
protected abstract LocalDateTime readLocalDateTime20();
public abstract long readMillis19();
protected abstract LocalDateTime readLocalDateTimeX(int len);
protected abstract LocalTime readLocalTime5();
protected abstract LocalTime readLocalTime8();
protected abstract LocalTime readLocalTime9();
protected abstract LocalTime readLocalTime10();
protected abstract LocalTime readLocalTime11();
protected abstract LocalTime readLocalTime12();
protected abstract LocalTime readLocalTime18();
protected abstract LocalDate readLocalDate8();
protected abstract LocalDate readLocalDate9();
protected abstract LocalDate readLocalDate10();
protected abstract LocalDate readLocalDate11();
protected abstract ZonedDateTime readZonedDateTimeX(int len);
public void readNumber(ValueConsumer consumer, boolean quoted) {
readNumber0();
Number number = getNumber();
consumer.accept(number);
}
public void readString(ValueConsumer consumer, boolean quoted) {
String str = readString(); //
if (quoted) {
consumer.accept(JSON.toJSONString(str));
} else {
consumer.accept(str);
}
}
protected abstract void readNumber0();
public abstract String readString();
public String[] readStringArray() {
if ((ch == 'n') && nextIfNull()) {
return null;
}
if (nextIfArrayStart()) {
String[] values = null;
int size = 0;
for (; ; ) {
if (nextIfArrayEnd()) {
if (values == null) {
values = new String[0];
}
break;
}
if (isEnd()) {
throw new JSONException(info("input end"));
}
if (values == null) {
values = new String[16];
} else {
if (size == values.length) {
values = Arrays.copyOf(values, values.length << 1);
}
}
values[size++] = readString();
}
nextIfComma();
if (values.length == size) {
return values;
}
return Arrays.copyOf(values, size);
}
if (this.ch == '"' || this.ch == '\'') {
String str = readString();
if (str.isEmpty()) {
return null;
}
throw new JSONException(info("not support input " + str));
}
throw new JSONException(info("not support input"));
}
public char readCharValue() {
String str = readString();
if (str == null || str.isEmpty()) {
wasNull = true;
return '\0';
}
return str.charAt(0);
}
public Character readCharacter() {
String str = readString();
if (str == null || str.isEmpty()) {
wasNull = true;
return '\0';
}
return Character.valueOf(str.charAt(0));
}
public abstract void readNull();
public abstract boolean readIfNull();
public abstract String getString();
public boolean wasNull() {
return wasNull;
}
public T read(Type type) {
boolean fieldBased = (context.features & Feature.FieldBased.mask) != 0;
ObjectReader objectReader = context.provider.getObjectReader(type, fieldBased);
return (T) objectReader.readObject(this, null, null, 0);
}
public final void read(List list) {
if (!nextIfArrayStart()) {
throw new JSONException("illegal input, offset " + offset + ", char " + ch);
}
level++;
if (level >= context.maxLevel) {
throw new JSONException("level too large : " + level);
}
for (; ; ) {
if (nextIfArrayEnd()) {
level--;
break;
}
Object item = ObjectReaderImplObject.INSTANCE.readObject(this, null, null, 0);
list.add(item);
nextIfComma();
}
nextIfComma();
}
public final void read(Collection list) {
if (!nextIfArrayStart()) {
throw new JSONException("illegal input, offset " + offset + ", char " + ch);
}
level++;
if (level >= context.maxLevel) {
throw new JSONException("level too large : " + level);
}
for (; ; ) {
if (nextIfArrayEnd()) {
level--;
break;
}
Object item = readAny();
list.add(item);
nextIfComma();
}
nextIfComma();
}
public final void readObject(Object object, Feature... features) {
long featuresLong = 0;
for (Feature feature : features) {
featuresLong |= feature.mask;
}
readObject(object, featuresLong);
}
public final void readObject(Object object, long features) {
if (object == null) {
throw new JSONException("object is null");
}
Class objectClass = object.getClass();
boolean fieldBased = ((context.features | features) & Feature.FieldBased.mask) != 0;
ObjectReader objectReader = context.provider.getObjectReader(objectClass, fieldBased);
if (objectReader instanceof ObjectReaderBean) {
ObjectReaderBean objectReaderBean = (ObjectReaderBean) objectReader;
objectReaderBean.readObject(this, object, features);
} else if (object instanceof Map) {
read((Map) object, features);
} else {
throw new JSONException("read object not support");
}
}
/**
* @since 2.0.35
*/
public void read(Map object, ObjectReader itemReader, long features) {
nextIfObjectStart();
Map map;
if (object instanceof Wrapper) {
map = ((Wrapper) object).unwrap(Map.class);
} else {
map = object;
}
long contextFeatures = features | context.getFeatures();
for (int i = 0; ; ++i) {
if (ch == '/') {
skipComment();
}
if (nextIfObjectEnd()) {
break;
}
if (i != 0 && !comma) {
throw new JSONException(info());
}
String name = readFieldName();
Object value = itemReader.readObject(this, itemReader.getObjectClass(), name, features);
if (value == null && (contextFeatures & Feature.IgnoreNullPropertyValue.mask) != 0) {
continue;
}
Object origin = map.put(name, value);
if (origin != null) {
if ((contextFeatures & JSONReader.Feature.DuplicateKeyValueAsArray.mask) != 0) {
if (origin instanceof Collection) {
((Collection) origin).add(value);
map.put(name, origin);
} else {
JSONArray array = JSONArray.of(origin, value);
map.put(name, array);
}
}
}
}
nextIfComma();
}
public void read(Map object, long features) {
boolean match = nextIfObjectStart();
boolean typeRedirect = false;
if (!match) {
if (typeRedirect = isTypeRedirect()) {
setTypeRedirect(false);
} else {
if (isString()) {
String str = readString();
if (str.isEmpty()) {
return;
}
}
throw new JSONException(info());
}
}
Map map;
if (object instanceof Wrapper) {
map = ((Wrapper) object).unwrap(Map.class);
} else {
map = object;
}
long contextFeatures = features | context.getFeatures();
for (int i = 0; ; ++i) {
if (ch == '/') {
skipComment();
}
if (nextIfObjectEnd()) {
break;
}
if (i != 0 && !comma) {
throw new JSONException(info());
}
Object name;
if (match || typeRedirect) {
if (ch >= '1' && ch <= '9') {
name = null;
} else {
name = readFieldName();
}
} else {
name = getFieldName();
match = true;
}
if (name == null) {
if (isNumber()) {
name = readNumber();
if ((context.features & Feature.NonStringKeyAsString.mask) != 0) {
name = name.toString();
}
if (comma) {
throw new JSONException(info("syntax error, illegal key-value"));
}
} else {
if ((context.features & Feature.AllowUnQuotedFieldNames.mask) != 0) {
name = readFieldNameUnquote();
} else {
throw new JSONException(info("not allow unquoted fieldName"));
}
}
if (ch == ':') {
next();
}
}
if (isReference()) {
String reference = readReference();
Object value = null;
if ("..".equals(reference)) {
value = map;
} else {
JSONPath jsonPath;
try {
jsonPath = JSONPath.of(reference);
} catch (Exception ignored) {
map.put(name, new JSONObject().fluentPut("$ref", reference));
continue;
}
addResolveTask(map, name, jsonPath);
}
map.put(name, value);
continue;
}
comma = false;
Object value;
switch (ch) {
case '-':
case '+':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
value = readNumber();
break;
case '[':
value = readArray();
break;
case '{':
if (typeRedirect) {
value = ObjectReaderImplObject.INSTANCE.readObject(this, null, name, features);
} else {
value = readObject();
}
break;
case '"':
case '\'':
value = readString();
break;
case 't':
case 'f':
value = readBoolValue();
break;
case 'n':
value = readNullOrNewDate();
break;
case '/':
next();
if (ch == '/') {
skipComment();
} else {
throw new JSONException("FASTJSON" + JSON.VERSION + "input not support " + ch + ", offset " + offset);
}
continue;
case 'S':
if (nextIfSet()) {
value = read(HashSet.class);
} else {
throw new JSONException("FASTJSON" + JSON.VERSION + "error, offset " + offset + ", char " + ch);
}
break;
case 'I':
if (nextIfInfinity()) {
value = Double.POSITIVE_INFINITY;
} else {
throw new JSONException("FASTJSON" + JSON.VERSION + "error, offset " + offset + ", char " + ch);
}
break;
case 'x':
value = readBinary();
break;
default:
throw new JSONException("FASTJSON" + JSON.VERSION + "error, offset " + offset + ", char " + ch);
}
if (value == null && (contextFeatures & Feature.IgnoreNullPropertyValue.mask) != 0) {
continue;
}
Object origin = map.put(name, value);
if (origin != null) {
if ((contextFeatures & JSONReader.Feature.DuplicateKeyValueAsArray.mask) != 0) {
if (origin instanceof Collection) {
((Collection) origin).add(value);
map.put(name, origin);
} else {
JSONArray array = JSONArray.of(origin, value);
map.put(name, array);
}
}
}
}
nextIfComma();
}
public final void read(Map object, Type keyType, Type valueType, long features) {
boolean match = nextIfObjectStart();
if (!match) {
throw new JSONException("illegal input, offset " + offset + ", char " + ch);
}
ObjectReader keyReader = context.getObjectReader(keyType);
ObjectReader valueReader = context.getObjectReader(valueType);
long contextFeatures = features | context.getFeatures();
for (int i = 0; ; ++i) {
if (ch == '/') {
skipComment();
}
if (nextIfObjectEnd()) {
break;
}
if (i != 0 && !comma) {
throw new JSONException(info());
}
Object name;
if (keyType == String.class) {
name = readFieldName();
} else {
name = keyReader.readObject(this, null, null, 0L);
nextIfMatch(':');
}
Object value = valueReader.readObject(this, null, null, 0L);
if (value == null && (contextFeatures & Feature.IgnoreNullPropertyValue.mask) != 0) {
continue;
}
Object origin = object.put(name, value);
if (origin != null) {
if ((contextFeatures & JSONReader.Feature.DuplicateKeyValueAsArray.mask) != 0) {
if (origin instanceof Collection) {
((Collection) origin).add(value);
object.put(name, origin);
} else {
JSONArray array = JSONArray.of(origin, value);
object.put(name, array);
}
}
}
}
nextIfComma();
}
public T read(Class type) {
boolean fieldBased = (context.features & Feature.FieldBased.mask) != 0;
ObjectReader objectReader = context.provider.getObjectReader(type, fieldBased);
return (T) objectReader.readObject(this, null, null, 0);
}
public Map readObject() {
nextIfObjectStart();
level++;
if (level >= context.maxLevel) {
throw new JSONException("level too large : " + level);
}
Map object;
if (context.objectSupplier == null) {
if ((context.features & Feature.UseNativeObject.mask) != 0) {
object = new HashMap();
} else {
object = new JSONObject();
}
} else {
object = context.objectSupplier.get();
}
for (int i = 0; ; ++i) {
if (ch == '}') {
next();
break;
}
Object name = readFieldName();
if (name == null) {
if (ch == EOI) {
throw new JSONException("input end");
}
if (ch == '-' || (ch >= '0' && ch <= '9')) {
readNumber0();
name = getNumber();
} else {
name = readFieldNameUnquote();
}
nextIfMatch(':');
}
if (i == 0 && (context.features & Feature.ErrorOnNotSupportAutoType.mask) != 0 && "@type".equals(name)) {
String typeName = readString();
throw new JSONException("autoType not support : " + typeName);
}
Object val;
switch (ch) {
case '-':
case '+':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
readNumber0();
val = getNumber();
break;
case '[':
val = readArray();
break;
case '{':
val = readObject();
break;
case '"':
case '\'':
val = readString();
break;
case 't':
case 'f':
val = readBoolValue();
break;
case 'n':
val = readNullOrNewDate();
break;
case '/':
skipComment();
continue;
case 'I':
if (nextIfInfinity()) {
val = Double.POSITIVE_INFINITY;
break;
} else {
throw new JSONException(info("illegal input " + ch));
}
case 'S':
if (nextIfSet()) {
val = read(Set.class);
break;
} else {
throw new JSONException(info("illegal input " + ch));
}
default:
throw new JSONException(info("illegal input " + ch));
}
if (val == null && (context.features & Feature.IgnoreNullPropertyValue.mask) != 0) {
continue;
}
Object origin = object.put(name, val);
if (origin != null) {
if ((context.features & JSONReader.Feature.DuplicateKeyValueAsArray.mask) != 0) {
if (origin instanceof Collection) {
((Collection) origin).add(val);
object.put(name, origin);
} else {
JSONArray array = JSONArray.of(origin, val);
object.put(name, array);
}
}
}
}
if (comma = (ch == ',')) {
next();
}
level--;
return object;
}
public abstract void skipComment();
public Boolean readBool() {
if (nextIfNull()) {
return null;
}
boolean boolValue = readBoolValue();
if (!boolValue && wasNull) {
return null;
}
return boolValue;
}
public abstract boolean readBoolValue();
public Object readAny() {
return read(Object.class);
}
public List readArray(Type itemType) {
if (nextIfNull()) {
return null;
}
if (!nextIfArrayStart()) {
throw new JSONException(info("syntax error : " + ch));
}
boolean fieldBased = (context.features & Feature.FieldBased.mask) != 0;
ObjectReader objectReader = context.provider.getObjectReader(itemType, fieldBased);
List list = new ArrayList();
for (Object item; !nextIfArrayEnd(); list.add(item)) {
int mark = offset;
item = objectReader.readObject(this, null, null, 0);
if (mark == offset || ch == '}' || ch == EOI) {
throw new JSONException("illegal input : " + ch + ", offset " + getOffset());
}
}
if (comma = (ch == ',')) {
next();
}
return list;
}
public List readList(Type[] types) {
if (nextIfNull()) {
return null;
}
if (!nextIfArrayStart()) {
throw new JSONException("syntax error : " + ch);
}
int i = 0, max = types.length;
List list = new ArrayList(max);
for (Object item; !nextIfArrayEnd() && i < max; list.add(item)) {
int mark = offset;
item = read(types[i++]);
if (mark == offset || ch == '}' || ch == EOI) {
throw new JSONException("illegal input : " + ch + ", offset " + getOffset());
}
}
if (i != max) {
throw new JSONException(info("element length mismatch"));
}
if (comma = (ch == ',')) {
next();
}
return list;
}
public final Object[] readArray(Type[] types) {
if (nextIfNull()) {
return null;
}
if (!nextIfArrayStart()) {
throw new JSONException(info("syntax error"));
}
int i = 0, max = types.length;
Object[] list = new Object[max];
for (Object item; !nextIfArrayEnd() && i < max; list[i++] = item) {
int mark = offset;
item = read(types[i]);
if (mark == offset || ch == '}' || ch == EOI) {
throw new JSONException("illegal input : " + ch + ", offset " + getOffset());
}
}
if (i != max) {
throw new JSONException(info("element length mismatch"));
}
if (comma = (ch == ',')) {
next();
}
return list;
}
public final void readArray(List list, Type itemType) {
readArray((Collection) list, itemType);
}
public final void readArray(Collection list, Type itemType) {
if (nextIfArrayStart()) {
while (!nextIfArrayEnd()) {
Object item = read(itemType);
list.add(item);
}
return;
}
if (isString()) {
String str = readString();
if (itemType == String.class) {
list.add(str);
} else {
Function typeConvert = context.getProvider().getTypeConvert(String.class, itemType);
if (typeConvert == null) {
throw new JSONException(info("not support input " + str));
}
if (str.indexOf(',') != -1) {
String[] items = str.split(",");
for (String strItem : items) {
Object item = typeConvert.apply(strItem);
list.add(item);
}
} else {
Object item = typeConvert.apply(str);
list.add(item);
}
}
} else {
Object item = read(itemType);
list.add(item);
}
if (comma = (ch == ',')) {
next();
}
}
public final JSONArray readJSONArray() {
JSONArray array = new JSONArray();
read(array);
return array;
}
public final JSONObject readJSONObject() {
JSONObject object = new JSONObject();
read(object, 0L);
return object;
}
public List readArray() {
next();
level++;
if (level >= context.maxLevel) {
throw new JSONException("level too large : " + level);
}
int i = 0;
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy