/src/main/java/com/alibaba/fastjson/JSONReader.java

https://github.com/alibaba/fastjson · Java · 346 lines · 296 code · 49 blank · 1 comment · 54 complexity · 292b51093e22212a2ed0dcae959c0392 MD5 · raw file

  1. package com.alibaba.fastjson;
  2. import static com.alibaba.fastjson.JSONStreamContext.ArrayValue;
  3. import static com.alibaba.fastjson.JSONStreamContext.PropertyKey;
  4. import static com.alibaba.fastjson.JSONStreamContext.PropertyValue;
  5. import static com.alibaba.fastjson.JSONStreamContext.StartArray;
  6. import static com.alibaba.fastjson.JSONStreamContext.StartObject;
  7. import java.io.Closeable;
  8. import java.io.Reader;
  9. import java.lang.reflect.Type;
  10. import java.util.Locale;
  11. import java.util.Map;
  12. import java.util.TimeZone;
  13. import com.alibaba.fastjson.parser.DefaultJSONParser;
  14. import com.alibaba.fastjson.parser.Feature;
  15. import com.alibaba.fastjson.parser.JSONLexer;
  16. import com.alibaba.fastjson.parser.JSONReaderScanner;
  17. import com.alibaba.fastjson.parser.JSONToken;
  18. import com.alibaba.fastjson.util.TypeUtils;
  19. public class JSONReader implements Closeable {
  20. private final DefaultJSONParser parser;
  21. private JSONStreamContext context;
  22. private transient JSONStreamContext lastContext;
  23. public JSONReader(Reader reader){
  24. this(reader, new Feature[0]);
  25. }
  26. public JSONReader(Reader reader, Feature... features){
  27. this(new JSONReaderScanner(reader));
  28. for (Feature feature : features) {
  29. this.config(feature, true);
  30. }
  31. }
  32. public JSONReader(JSONLexer lexer){
  33. this(new DefaultJSONParser(lexer));
  34. }
  35. public JSONReader(DefaultJSONParser parser){
  36. this.parser = parser;
  37. }
  38. public void setTimzeZone(TimeZone timezone) {
  39. this.parser.lexer.setTimeZone(timezone);
  40. }
  41. public void setLocale(Locale locale) {
  42. this.parser.lexer.setLocale(locale);
  43. }
  44. public void config(Feature feature, boolean state) {
  45. this.parser.config(feature, state);
  46. }
  47. public Locale getLocal() {
  48. return this.parser.lexer.getLocale();
  49. }
  50. public TimeZone getTimzeZone() {
  51. return this.parser.lexer.getTimeZone();
  52. }
  53. public void startObject() {
  54. if (context == null) {
  55. context = new JSONStreamContext(null, JSONStreamContext.StartObject);
  56. } else {
  57. startStructure();
  58. if (lastContext != null
  59. && lastContext.parent == context) {
  60. context = lastContext;
  61. if (context.state != JSONStreamContext.StartObject) {
  62. context.state = JSONStreamContext.StartObject;
  63. }
  64. } else {
  65. context = new JSONStreamContext(context, JSONStreamContext.StartObject);
  66. }
  67. }
  68. this.parser.accept(JSONToken.LBRACE, JSONToken.IDENTIFIER);
  69. }
  70. public void endObject() {
  71. this.parser.accept(JSONToken.RBRACE);
  72. endStructure();
  73. }
  74. public void startArray() {
  75. if (context == null) {
  76. context = new JSONStreamContext(null, StartArray);
  77. } else {
  78. startStructure();
  79. context = new JSONStreamContext(context, StartArray);
  80. }
  81. this.parser.accept(JSONToken.LBRACKET);
  82. }
  83. public void endArray() {
  84. this.parser.accept(JSONToken.RBRACKET);
  85. endStructure();
  86. }
  87. private void startStructure() {
  88. final int state = context.state;
  89. switch (state) {
  90. case PropertyKey:
  91. parser.accept(JSONToken.COLON);
  92. break;
  93. case PropertyValue:
  94. case ArrayValue:
  95. parser.accept(JSONToken.COMMA);
  96. break;
  97. case StartArray:
  98. case StartObject:
  99. break;
  100. default:
  101. throw new JSONException("illegal state : " + context.state);
  102. }
  103. }
  104. private void endStructure() {
  105. lastContext = context;
  106. context = context.parent;
  107. if (context == null) {
  108. return;
  109. }
  110. final int state = context.state;
  111. int newState = -1;
  112. switch (state) {
  113. case PropertyKey:
  114. newState = PropertyValue;
  115. break;
  116. case StartArray:
  117. newState = ArrayValue;
  118. break;
  119. case PropertyValue:
  120. case StartObject:
  121. newState = PropertyKey;
  122. break;
  123. default:
  124. break;
  125. }
  126. if (newState != -1) {
  127. context.state = newState;
  128. }
  129. }
  130. public boolean hasNext() {
  131. if (context == null) {
  132. throw new JSONException("context is null");
  133. }
  134. final int token = parser.lexer.token();
  135. final int state = context.state;
  136. switch (state) {
  137. case StartArray:
  138. case ArrayValue:
  139. return token != JSONToken.RBRACKET;
  140. case StartObject:
  141. case PropertyValue:
  142. return token != JSONToken.RBRACE;
  143. default:
  144. throw new JSONException("illegal state : " + state);
  145. }
  146. }
  147. public int peek() {
  148. return parser.lexer.token();
  149. }
  150. public void close() {
  151. parser.close();
  152. }
  153. public Integer readInteger() {
  154. Object object;
  155. if (context == null) {
  156. object = parser.parse();
  157. } else {
  158. readBefore();
  159. object = parser.parse();
  160. readAfter();
  161. }
  162. return TypeUtils.castToInt(object);
  163. }
  164. public Long readLong() {
  165. Object object;
  166. if (context == null) {
  167. object = parser.parse();
  168. } else {
  169. readBefore();
  170. object = parser.parse();
  171. readAfter();
  172. }
  173. return TypeUtils.castToLong(object);
  174. }
  175. public String readString() {
  176. Object object;
  177. if (context == null) {
  178. object = parser.parse();
  179. } else {
  180. readBefore();
  181. JSONLexer lexer = parser.lexer;
  182. if (context.state == JSONStreamContext.StartObject && lexer.token() == JSONToken.IDENTIFIER) {
  183. object = lexer.stringVal();
  184. lexer.nextToken();
  185. } else {
  186. object = parser.parse();
  187. }
  188. readAfter();
  189. }
  190. return TypeUtils.castToString(object);
  191. }
  192. public <T> T readObject(TypeReference<T> typeRef) {
  193. return readObject(typeRef.getType());
  194. }
  195. public <T> T readObject(Type type) {
  196. if (context == null) {
  197. return parser.parseObject(type);
  198. }
  199. readBefore();
  200. T object = parser.parseObject(type);
  201. readAfter();
  202. return object;
  203. }
  204. public <T> T readObject(Class<T> type) {
  205. if (context == null) {
  206. return parser.parseObject(type);
  207. }
  208. readBefore();
  209. T object = parser.parseObject(type);
  210. parser.handleResovleTask(object);
  211. readAfter();
  212. return object;
  213. }
  214. public void readObject(Object object) {
  215. if (context == null) {
  216. parser.parseObject(object);
  217. return;
  218. }
  219. readBefore();
  220. parser.parseObject(object);
  221. readAfter();
  222. }
  223. public Object readObject() {
  224. if (context == null) {
  225. return parser.parse();
  226. }
  227. readBefore();
  228. Object object;
  229. switch (context.state) {
  230. case StartObject:
  231. case PropertyValue:
  232. object = parser.parseKey();
  233. break;
  234. default:
  235. object = parser.parse();
  236. break;
  237. }
  238. readAfter();
  239. return object;
  240. }
  241. @SuppressWarnings("rawtypes")
  242. public Object readObject(Map object) {
  243. if (context == null) {
  244. return parser.parseObject(object);
  245. }
  246. readBefore();
  247. Object value = parser.parseObject(object);
  248. readAfter();
  249. return value;
  250. }
  251. private void readBefore() {
  252. int state = context.state;
  253. // before
  254. switch (state) {
  255. case PropertyKey:
  256. parser.accept(JSONToken.COLON);
  257. break;
  258. case PropertyValue:
  259. parser.accept(JSONToken.COMMA, JSONToken.IDENTIFIER);
  260. break;
  261. case ArrayValue:
  262. parser.accept(JSONToken.COMMA);
  263. break;
  264. case StartObject:
  265. break;
  266. case StartArray:
  267. break;
  268. default:
  269. throw new JSONException("illegal state : " + state);
  270. }
  271. }
  272. private void readAfter() {
  273. int state = context.state;
  274. int newStat = -1;
  275. switch (state) {
  276. case StartObject:
  277. newStat = PropertyKey;
  278. break;
  279. case PropertyKey:
  280. newStat = PropertyValue;
  281. break;
  282. case PropertyValue:
  283. newStat = PropertyKey;
  284. break;
  285. case ArrayValue:
  286. break;
  287. case StartArray:
  288. newStat = ArrayValue;
  289. break;
  290. default:
  291. throw new JSONException("illegal state : " + state);
  292. }
  293. if (newStat != -1) {
  294. context.state = newStat;
  295. }
  296. }
  297. }