/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

  1. package com.alibaba.fastjson;
  2. import java.io.Closeable;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.Reader;
  6. public abstract class JSONValidator implements Cloneable, Closeable {
  7. public enum Type {
  8. Object, Array, Value
  9. }
  10. protected boolean eof;
  11. protected int pos = -1;
  12. protected char ch;
  13. protected Type type;
  14. private Boolean validateResult;
  15. protected int count = 0;
  16. protected boolean supportMultiValue = false;
  17. public static JSONValidator fromUtf8(byte[] jsonBytes) {
  18. return new UTF8Validator(jsonBytes);
  19. }
  20. public static JSONValidator fromUtf8(InputStream is) {
  21. return new UTF8InputStreamValidator(is);
  22. }
  23. public static JSONValidator from(String jsonStr) {
  24. return new UTF16Validator(jsonStr);
  25. }
  26. public static JSONValidator from(Reader r) {
  27. return new ReaderValidator(r);
  28. }
  29. public boolean isSupportMultiValue() {
  30. return supportMultiValue;
  31. }
  32. public JSONValidator setSupportMultiValue(boolean supportMultiValue) {
  33. this.supportMultiValue = supportMultiValue;
  34. return this;
  35. }
  36. public Type getType() {
  37. if (type == null) {
  38. validate();
  39. }
  40. return type;
  41. }
  42. abstract void next();
  43. public boolean validate() {
  44. if (validateResult != null) {
  45. return validateResult;
  46. }
  47. for (;;) {
  48. if (!any()) {
  49. validateResult = false;
  50. return false;
  51. }
  52. skipWhiteSpace();
  53. count++;
  54. if (eof) {
  55. validateResult = true;
  56. return true;
  57. }
  58. if (supportMultiValue) {
  59. skipWhiteSpace();
  60. if (eof) {
  61. break;
  62. }
  63. continue;
  64. } else {
  65. validateResult = false;
  66. return false;
  67. }
  68. }
  69. validateResult = true;
  70. return true;
  71. }
  72. public void close() throws IOException {
  73. }
  74. private boolean any() {
  75. switch (ch) {
  76. case '{':
  77. next();
  78. while (isWhiteSpace(ch)) {
  79. next();
  80. }
  81. if (ch == '}') {
  82. next();
  83. type = Type.Object;
  84. return true;
  85. }
  86. for (;;) {
  87. if (ch == '"') {
  88. fieldName();
  89. } else {
  90. return false;
  91. }
  92. skipWhiteSpace();
  93. if (ch == ':') {
  94. next();
  95. } else {
  96. return false;
  97. }
  98. skipWhiteSpace();
  99. if (!any()) {
  100. return false;
  101. }
  102. // kv 结束时,只能是 "," 或 "}"
  103. skipWhiteSpace();
  104. if (ch == ',') {
  105. next();
  106. skipWhiteSpace();
  107. } else if (ch == '}') {
  108. next();
  109. type = Type.Object;
  110. return true;
  111. } else {
  112. return false;
  113. }
  114. }
  115. case '[':
  116. next();
  117. skipWhiteSpace();
  118. if (ch == ']') {
  119. next();
  120. type = Type.Array;
  121. return true;
  122. }
  123. for (;;) {
  124. if (!any()) {
  125. return false;
  126. }
  127. skipWhiteSpace();
  128. if (ch == ',') {
  129. next();
  130. skipWhiteSpace();
  131. } else if (ch == ']') {
  132. next();
  133. type = Type.Array;
  134. return true;
  135. }
  136. else {
  137. return false;
  138. }
  139. }
  140. case '0':
  141. case '1':
  142. case '2':
  143. case '3':
  144. case '4':
  145. case '5':
  146. case '6':
  147. case '7':
  148. case '8':
  149. case '9':
  150. case '+':
  151. case '-':
  152. if (ch == '-' || ch == '+') {
  153. next();
  154. skipWhiteSpace();
  155. if (ch < '0' || ch > '9') {
  156. return false;
  157. }
  158. }
  159. do {
  160. next();
  161. } while (ch >= '0' && ch <= '9');
  162. if (ch == '.') {
  163. next();
  164. // bug fix: 0.e7 should not pass the test
  165. if (ch < '0' || ch > '9') {
  166. return false;
  167. }
  168. while (ch >= '0' && ch <= '9') {
  169. next();
  170. }
  171. }
  172. if (ch == 'e' || ch == 'E') {
  173. next();
  174. if (ch == '-' || ch == '+') {
  175. next();
  176. }
  177. if (ch >= '0' && ch <= '9') {
  178. next();
  179. }
  180. else {
  181. return false;
  182. }
  183. while (ch >= '0' && ch <= '9') {
  184. next();
  185. }
  186. }
  187. type = Type.Value;
  188. break;
  189. case '"':
  190. next();
  191. for (;;) {
  192. if (eof) {
  193. return false;
  194. }
  195. if (ch == '\\') {
  196. next();
  197. if (ch == 'u') {
  198. next();
  199. next();
  200. next();
  201. next();
  202. next();
  203. } else {
  204. next();
  205. }
  206. } else if (ch == '"') {
  207. next();
  208. type = Type.Value;
  209. return true;
  210. } else {
  211. next();
  212. }
  213. }
  214. case 't':
  215. next();
  216. if (ch != 'r') {
  217. return false;
  218. }
  219. next();
  220. if (ch != 'u') {
  221. return false;
  222. }
  223. next();
  224. if (ch != 'e') {
  225. return false;
  226. }
  227. next();
  228. if (isWhiteSpace(ch) || ch == ',' || ch == ']' || ch == '}' || ch == '\0') {
  229. type = Type.Value;
  230. return true;
  231. }
  232. return false;
  233. case 'f':
  234. next();
  235. if (ch != 'a') {
  236. return false;
  237. }
  238. next();
  239. if (ch != 'l') {
  240. return false;
  241. }
  242. next();
  243. if (ch != 's') {
  244. return false;
  245. }
  246. next();
  247. if (ch != 'e') {
  248. return false;
  249. }
  250. next();
  251. if (isWhiteSpace(ch) || ch == ',' || ch == ']' || ch == '}' || ch == '\0') {
  252. type = Type.Value;
  253. return true;
  254. }
  255. return false;
  256. case 'n':
  257. next();
  258. if (ch != 'u') {
  259. return false;
  260. }
  261. next();
  262. if (ch != 'l') {
  263. return false;
  264. }
  265. next();
  266. if (ch != 'l') {
  267. return false;
  268. }
  269. next();
  270. if (isWhiteSpace(ch) || ch == ',' || ch == ']' || ch == '}' || ch == '\0') {
  271. type = Type.Value;
  272. return true;
  273. }
  274. return false;
  275. default:
  276. return false;
  277. }
  278. return true;
  279. }
  280. protected void fieldName()
  281. {
  282. next();
  283. for (; ; ) {
  284. if (ch == '\\') {
  285. next();
  286. if (ch == 'u') {
  287. next();
  288. next();
  289. next();
  290. next();
  291. next();
  292. } else {
  293. next();
  294. }
  295. }
  296. else if (ch == '"') {
  297. next();
  298. break;
  299. }
  300. else {
  301. next();
  302. }
  303. }
  304. }
  305. protected boolean string()
  306. {
  307. next();
  308. for (; !eof; ) {
  309. if (ch == '\\') {
  310. next();
  311. if (ch == 'u') {
  312. next();
  313. next();
  314. next();
  315. next();
  316. next();
  317. } else {
  318. next();
  319. }
  320. }
  321. else if (ch == '"') {
  322. next();
  323. return true;
  324. }
  325. else {
  326. next();
  327. }
  328. }
  329. return false;
  330. }
  331. void skipWhiteSpace() {
  332. while (isWhiteSpace(ch)) {
  333. next();
  334. }
  335. }
  336. static final boolean isWhiteSpace(char ch) {
  337. return ch == ' '
  338. || ch == '\t'
  339. || ch == '\r'
  340. || ch == '\n'
  341. || ch == '\f'
  342. || ch == '\b'
  343. ;
  344. }
  345. static class UTF8Validator extends JSONValidator {
  346. private final byte[] bytes;
  347. public UTF8Validator(byte[] bytes) {
  348. this.bytes = bytes;
  349. next();
  350. skipWhiteSpace();
  351. }
  352. void next() {
  353. ++pos;
  354. if (pos >= bytes.length) {
  355. ch = '\0';
  356. eof = true;
  357. } else {
  358. ch = (char) bytes[pos];
  359. }
  360. }
  361. }
  362. static class UTF8InputStreamValidator extends JSONValidator {
  363. private final static ThreadLocal<byte[]> bufLocal = new ThreadLocal<byte[]>();
  364. private final InputStream is;
  365. private byte[] buf;
  366. private int end = -1;
  367. private int readCount = 0;
  368. public UTF8InputStreamValidator(InputStream is) {
  369. this.is = is;
  370. buf = bufLocal.get();
  371. if (buf != null) {
  372. bufLocal.set(null);
  373. } else {
  374. buf = new byte[1024 * 8];
  375. }
  376. next();
  377. skipWhiteSpace();
  378. }
  379. void next() {
  380. if (pos < end) {
  381. ch = (char) buf[++pos];
  382. } else {
  383. if (!eof) {
  384. int len;
  385. try {
  386. len = is.read(buf, 0, buf.length);
  387. readCount++;
  388. } catch (IOException ex) {
  389. throw new JSONException("read error");
  390. }
  391. if (len > 0) {
  392. ch = (char) buf[0];
  393. pos = 0;
  394. end = len - 1;
  395. }
  396. else if (len == -1) {
  397. pos = 0;
  398. end = 0;
  399. buf = null;
  400. ch = '\0';
  401. eof = true;
  402. } else {
  403. pos = 0;
  404. end = 0;
  405. buf = null;
  406. ch = '\0';
  407. eof = true;
  408. throw new JSONException("read error");
  409. }
  410. }
  411. }
  412. }
  413. public void close() throws IOException {
  414. bufLocal.set(buf);
  415. is.close();
  416. }
  417. }
  418. static class UTF16Validator extends JSONValidator {
  419. private final String str;
  420. public UTF16Validator(String str) {
  421. this.str = str;
  422. next();
  423. skipWhiteSpace();
  424. }
  425. void next() {
  426. ++pos;
  427. if (pos >= str.length()) {
  428. ch = '\0';
  429. eof = true;
  430. } else {
  431. ch = str.charAt(pos);
  432. }
  433. }
  434. protected final void fieldName()
  435. {
  436. for (int i = pos + 1; i < str.length(); ++i) {
  437. char ch = str.charAt(i);
  438. if (ch == '\\') {
  439. break;
  440. }
  441. if (ch == '\"') {
  442. this.ch = str.charAt(i + 1);
  443. pos = i + 1;
  444. return;
  445. }
  446. }
  447. next();
  448. for (; ; ) {
  449. if (ch == '\\') {
  450. next();
  451. if (ch == 'u') {
  452. next();
  453. next();
  454. next();
  455. next();
  456. next();
  457. } else {
  458. next();
  459. }
  460. }
  461. else if (ch == '"') {
  462. next();
  463. break;
  464. }
  465. else if(eof){
  466. break;
  467. }else {
  468. next();
  469. }
  470. }
  471. }
  472. }
  473. static class ReaderValidator extends JSONValidator {
  474. private final static ThreadLocal<char[]> bufLocal = new ThreadLocal<char[]>();
  475. final Reader r;
  476. private char[] buf;
  477. private int end = -1;
  478. private int readCount = 0;
  479. ReaderValidator(Reader r) {
  480. this.r = r;
  481. buf = bufLocal.get();
  482. if (buf != null) {
  483. bufLocal.set(null);
  484. } else {
  485. buf = new char[1024 * 8];
  486. }
  487. next();
  488. skipWhiteSpace();
  489. }
  490. void next() {
  491. if (pos < end) {
  492. ch = buf[++pos];
  493. } else {
  494. if (!eof) {
  495. int len;
  496. try {
  497. len = r.read(buf, 0, buf.length);
  498. readCount++;
  499. } catch (IOException ex) {
  500. throw new JSONException("read error");
  501. }
  502. if (len > 0) {
  503. ch = buf[0];
  504. pos = 0;
  505. end = len - 1;
  506. }
  507. else if (len == -1) {
  508. pos = 0;
  509. end = 0;
  510. buf = null;
  511. ch = '\0';
  512. eof = true;
  513. } else {
  514. pos = 0;
  515. end = 0;
  516. buf = null;
  517. ch = '\0';
  518. eof = true;
  519. throw new JSONException("read error");
  520. }
  521. }
  522. }
  523. }
  524. public void close() throws IOException {
  525. bufLocal.set(buf);
  526. r.close();
  527. }
  528. }
  529. }