/src/main/java/com/alibaba/fastjson/JSONValidator.java
https://github.com/alibaba/fastjson · Java · 617 lines · 579 code · 38 blank · 0 comment · 50 complexity · 2c8fa4df63bcf2a2b9e8ada9afa7cdad MD5 · raw file
- package com.alibaba.fastjson;
- import java.io.Closeable;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.Reader;
- public abstract class JSONValidator implements Cloneable, Closeable {
- public enum Type {
- Object, Array, Value
- }
- protected boolean eof;
- protected int pos = -1;
- protected char ch;
- protected Type type;
- private Boolean validateResult;
- protected int count = 0;
- protected boolean supportMultiValue = false;
- public static JSONValidator fromUtf8(byte[] jsonBytes) {
- return new UTF8Validator(jsonBytes);
- }
- public static JSONValidator fromUtf8(InputStream is) {
- return new UTF8InputStreamValidator(is);
- }
- public static JSONValidator from(String jsonStr) {
- return new UTF16Validator(jsonStr);
- }
- public static JSONValidator from(Reader r) {
- return new ReaderValidator(r);
- }
- public boolean isSupportMultiValue() {
- return supportMultiValue;
- }
- public JSONValidator setSupportMultiValue(boolean supportMultiValue) {
- this.supportMultiValue = supportMultiValue;
- return this;
- }
- public Type getType() {
- if (type == null) {
- validate();
- }
- return type;
- }
- abstract void next();
- public boolean validate() {
- if (validateResult != null) {
- return validateResult;
- }
- for (;;) {
- if (!any()) {
- validateResult = false;
- return false;
- }
- skipWhiteSpace();
- count++;
- if (eof) {
- validateResult = true;
- return true;
- }
- if (supportMultiValue) {
- skipWhiteSpace();
- if (eof) {
- break;
- }
- continue;
- } else {
- validateResult = false;
- return false;
- }
- }
- validateResult = true;
- return true;
- }
- public void close() throws IOException {
- }
- private boolean any() {
- switch (ch) {
- case '{':
- next();
- while (isWhiteSpace(ch)) {
- next();
- }
- if (ch == '}') {
- next();
- type = Type.Object;
- return true;
- }
- for (;;) {
- if (ch == '"') {
- fieldName();
- } else {
- return false;
- }
- skipWhiteSpace();
- if (ch == ':') {
- next();
- } else {
- return false;
- }
- skipWhiteSpace();
- if (!any()) {
- return false;
- }
- // kv 结束时,只能是 "," 或 "}"
- skipWhiteSpace();
- if (ch == ',') {
- next();
- skipWhiteSpace();
- } else if (ch == '}') {
- next();
- type = Type.Object;
- return true;
- } else {
- return false;
- }
- }
- case '[':
- next();
- skipWhiteSpace();
- if (ch == ']') {
- next();
- type = Type.Array;
- return true;
- }
- for (;;) {
- if (!any()) {
- return false;
- }
- skipWhiteSpace();
- if (ch == ',') {
- next();
- skipWhiteSpace();
- } else if (ch == ']') {
- next();
- type = Type.Array;
- return true;
- }
- else {
- return false;
- }
- }
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '+':
- case '-':
- if (ch == '-' || ch == '+') {
- next();
- skipWhiteSpace();
- if (ch < '0' || ch > '9') {
- return false;
- }
- }
- do {
- next();
- } while (ch >= '0' && ch <= '9');
- if (ch == '.') {
- next();
- // bug fix: 0.e7 should not pass the test
- if (ch < '0' || ch > '9') {
- return false;
- }
- while (ch >= '0' && ch <= '9') {
- next();
- }
- }
- if (ch == 'e' || ch == 'E') {
- next();
- if (ch == '-' || ch == '+') {
- next();
- }
- if (ch >= '0' && ch <= '9') {
- next();
- }
- else {
- return false;
- }
- while (ch >= '0' && ch <= '9') {
- next();
- }
- }
- type = Type.Value;
- break;
- case '"':
- next();
- for (;;) {
- if (eof) {
- return false;
- }
- if (ch == '\\') {
- next();
- if (ch == 'u') {
- next();
- next();
- next();
- next();
- next();
- } else {
- next();
- }
- } else if (ch == '"') {
- next();
- type = Type.Value;
- return true;
- } else {
- next();
- }
- }
- case 't':
- next();
- if (ch != 'r') {
- return false;
- }
- next();
- if (ch != 'u') {
- return false;
- }
- next();
- if (ch != 'e') {
- return false;
- }
- next();
- if (isWhiteSpace(ch) || ch == ',' || ch == ']' || ch == '}' || ch == '\0') {
- type = Type.Value;
- return true;
- }
- return false;
- case 'f':
- next();
- if (ch != 'a') {
- return false;
- }
- next();
- if (ch != 'l') {
- return false;
- }
- next();
- if (ch != 's') {
- return false;
- }
- next();
- if (ch != 'e') {
- return false;
- }
- next();
- if (isWhiteSpace(ch) || ch == ',' || ch == ']' || ch == '}' || ch == '\0') {
- type = Type.Value;
- return true;
- }
- return false;
- case 'n':
- next();
- if (ch != 'u') {
- return false;
- }
- next();
- if (ch != 'l') {
- return false;
- }
- next();
- if (ch != 'l') {
- return false;
- }
- next();
- if (isWhiteSpace(ch) || ch == ',' || ch == ']' || ch == '}' || ch == '\0') {
- type = Type.Value;
- return true;
- }
- return false;
- default:
- return false;
- }
- return true;
- }
- protected void fieldName()
- {
- next();
- for (; ; ) {
- if (ch == '\\') {
- next();
- if (ch == 'u') {
- next();
- next();
- next();
- next();
- next();
- } else {
- next();
- }
- }
- else if (ch == '"') {
- next();
- break;
- }
- else {
- next();
- }
- }
- }
- protected boolean string()
- {
- next();
- for (; !eof; ) {
- if (ch == '\\') {
- next();
- if (ch == 'u') {
- next();
- next();
- next();
- next();
- next();
- } else {
- next();
- }
- }
- else if (ch == '"') {
- next();
- return true;
- }
- else {
- next();
- }
- }
- return false;
- }
- void skipWhiteSpace() {
- while (isWhiteSpace(ch)) {
- next();
- }
- }
- static final boolean isWhiteSpace(char ch) {
- return ch == ' '
- || ch == '\t'
- || ch == '\r'
- || ch == '\n'
- || ch == '\f'
- || ch == '\b'
- ;
- }
- static class UTF8Validator extends JSONValidator {
- private final byte[] bytes;
- public UTF8Validator(byte[] bytes) {
- this.bytes = bytes;
- next();
- skipWhiteSpace();
- }
- void next() {
- ++pos;
- if (pos >= bytes.length) {
- ch = '\0';
- eof = true;
- } else {
- ch = (char) bytes[pos];
- }
- }
- }
- static class UTF8InputStreamValidator extends JSONValidator {
- private final static ThreadLocal<byte[]> bufLocal = new ThreadLocal<byte[]>();
- private final InputStream is;
- private byte[] buf;
- private int end = -1;
- private int readCount = 0;
- public UTF8InputStreamValidator(InputStream is) {
- this.is = is;
- buf = bufLocal.get();
- if (buf != null) {
- bufLocal.set(null);
- } else {
- buf = new byte[1024 * 8];
- }
- next();
- skipWhiteSpace();
- }
- void next() {
- if (pos < end) {
- ch = (char) buf[++pos];
- } else {
- if (!eof) {
- int len;
- try {
- len = is.read(buf, 0, buf.length);
- readCount++;
- } catch (IOException ex) {
- throw new JSONException("read error");
- }
- if (len > 0) {
- ch = (char) buf[0];
- pos = 0;
- end = len - 1;
- }
- else if (len == -1) {
- pos = 0;
- end = 0;
- buf = null;
- ch = '\0';
- eof = true;
- } else {
- pos = 0;
- end = 0;
- buf = null;
- ch = '\0';
- eof = true;
- throw new JSONException("read error");
- }
- }
- }
- }
- public void close() throws IOException {
- bufLocal.set(buf);
- is.close();
- }
- }
- static class UTF16Validator extends JSONValidator {
- private final String str;
- public UTF16Validator(String str) {
- this.str = str;
- next();
- skipWhiteSpace();
- }
- void next() {
- ++pos;
- if (pos >= str.length()) {
- ch = '\0';
- eof = true;
- } else {
- ch = str.charAt(pos);
- }
- }
- protected final void fieldName()
- {
- for (int i = pos + 1; i < str.length(); ++i) {
- char ch = str.charAt(i);
- if (ch == '\\') {
- break;
- }
- if (ch == '\"') {
- this.ch = str.charAt(i + 1);
- pos = i + 1;
- return;
- }
- }
- next();
- for (; ; ) {
- if (ch == '\\') {
- next();
- if (ch == 'u') {
- next();
- next();
- next();
- next();
- next();
- } else {
- next();
- }
- }
- else if (ch == '"') {
- next();
- break;
- }
- else if(eof){
- break;
- }else {
- next();
- }
- }
- }
- }
- static class ReaderValidator extends JSONValidator {
- private final static ThreadLocal<char[]> bufLocal = new ThreadLocal<char[]>();
- final Reader r;
- private char[] buf;
- private int end = -1;
- private int readCount = 0;
- ReaderValidator(Reader r) {
- this.r = r;
- buf = bufLocal.get();
- if (buf != null) {
- bufLocal.set(null);
- } else {
- buf = new char[1024 * 8];
- }
- next();
- skipWhiteSpace();
- }
- void next() {
- if (pos < end) {
- ch = buf[++pos];
- } else {
- if (!eof) {
- int len;
- try {
- len = r.read(buf, 0, buf.length);
- readCount++;
- } catch (IOException ex) {
- throw new JSONException("read error");
- }
- if (len > 0) {
- ch = buf[0];
- pos = 0;
- end = len - 1;
- }
- else if (len == -1) {
- pos = 0;
- end = 0;
- buf = null;
- ch = '\0';
- eof = true;
- } else {
- pos = 0;
- end = 0;
- buf = null;
- ch = '\0';
- eof = true;
- throw new JSONException("read error");
- }
- }
- }
- }
- public void close() throws IOException {
- bufLocal.set(buf);
- r.close();
- }
- }
- }