├── .idea
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── misc.xml
├── modules.xml
├── uiDesigner.xml
└── vcs.xml
├── README.md
├── SimpleJSON.iml
└── src
├── GsonTest.java
├── HttpUtil.java
├── JParsingTest.java
├── JSONParsingTest.java
├── SimpleJSONTest.java
├── exception
└── JsonParseException.java
├── model
└── LatestNews.java
├── parser
├── JArray.java
├── JObject.java
├── Json.java
├── Key.java
├── Parser.java
├── Primary.java
└── Value.java
└── tokenizer
├── Token.java
├── TokenType.java
└── Tokenizer.java
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/uiDesigner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 | -
9 |
10 |
11 | -
12 |
13 |
14 | -
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
23 | -
24 |
25 |
26 |
27 |
28 |
29 | -
30 |
31 |
32 |
33 |
34 |
35 | -
36 |
37 |
38 |
39 |
40 |
41 | -
42 |
43 |
44 |
45 |
46 | -
47 |
48 |
49 |
50 |
51 | -
52 |
53 |
54 |
55 |
56 | -
57 |
58 |
59 |
60 |
61 | -
62 |
63 |
64 |
65 |
66 | -
67 |
68 |
69 |
70 |
71 | -
72 |
73 |
74 | -
75 |
76 |
77 |
78 |
79 | -
80 |
81 |
82 |
83 |
84 | -
85 |
86 |
87 |
88 |
89 | -
90 |
91 |
92 |
93 |
94 | -
95 |
96 |
97 |
98 |
99 | -
100 |
101 |
102 | -
103 |
104 |
105 | -
106 |
107 |
108 | -
109 |
110 |
111 | -
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
119 | -
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SimpleJSON
2 |
3 | [一起写一个JSON解析器](http://www.cnblogs.com/absfree/p/5502705.html)
4 |
--------------------------------------------------------------------------------
/SimpleJSON.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/GsonTest.java:
--------------------------------------------------------------------------------
1 | import com.google.gson.Gson;
2 | import model.LatestNews;
3 |
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.Closeable;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.net.HttpURLConnection;
9 | import java.net.URL;
10 |
11 | /**
12 | * Created by Administrator on 2016/5/17.
13 | */
14 | public class GsonTest {
15 | public static final String urlString = "http://news-at.zhihu.com/api/4/news/latest";
16 |
17 | public static void main(String[] args) {
18 | LatestNews latest = new LatestNews();
19 | String jsonString = new String(HttpUtil.get(urlString));
20 |
21 | long startTime = System.currentTimeMillis();
22 |
23 | latest = (new Gson()).fromJson(jsonString, LatestNews.class);
24 |
25 | long endTime = System.currentTimeMillis();
26 | double time = (double) (endTime - startTime) / 1000.0;
27 | System.out.println("took " + time + "seconds.");
28 |
29 | System.out.println(latest.getDate());
30 | for (int i = 0; i < latest.getTop_stories().size(); i++) {
31 | System.out.println(latest.getTop_stories().get(i));
32 | }
33 | for (int i = 0; i < latest.getStories().size(); i++) {
34 | System.out.println(latest.getStories().get(i));
35 | }
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/HttpUtil.java:
--------------------------------------------------------------------------------
1 | import java.io.ByteArrayOutputStream;
2 | import java.io.Closeable;
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.net.HttpURLConnection;
6 | import java.net.URL;
7 |
8 | /**
9 | * Created by Administrator on 2016/5/22.
10 | */
11 | public class HttpUtil {
12 | public static byte[] get(String urlString) {
13 | HttpURLConnection urlConnection = null;
14 | try {
15 | URL url = new URL(urlString);
16 | urlConnection = (HttpURLConnection) url.openConnection();
17 | //设置请求方法
18 | urlConnection.setRequestMethod("GET");
19 | //设置超时时间
20 | urlConnection.setConnectTimeout(5000);
21 | urlConnection.setReadTimeout(3000);
22 |
23 | //获取响应的状态码
24 | int responseCode = urlConnection.getResponseCode();
25 | if (responseCode == 200) {
26 | ByteArrayOutputStream bos = new ByteArrayOutputStream();
27 | InputStream in = urlConnection.getInputStream();
28 | byte[] buffer = new byte[4 * 1024];
29 | int len = -1;
30 | while((len = in.read(buffer)) != -1) {
31 | bos.write(buffer, 0, len);
32 | }
33 | close(in);
34 | byte[] result = bos.toByteArray();
35 | close(bos);
36 | return result;
37 | } else {
38 | return null;
39 | }
40 | } catch (Exception e) {
41 | e.printStackTrace();
42 | } finally {
43 | if (urlConnection != null) {
44 | urlConnection.disconnect();
45 | }
46 | }
47 |
48 | return null;
49 | }
50 |
51 | private static void close(Closeable stream) {
52 | if (stream != null) {
53 | try {
54 | stream.close();
55 | } catch (IOException e) {
56 | e.printStackTrace();
57 | }
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/JParsingTest.java:
--------------------------------------------------------------------------------
1 | import model.LatestNews;
2 | import org.json.JSONArray;
3 | import org.json.JSONException;
4 | import org.json.JSONObject;
5 | import parser.JArray;
6 | import parser.JObject;
7 |
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | import static parser.Parser.parseJSONObject;
12 |
13 | /**
14 | * Created by Administrator on 2016/5/22.
15 | */
16 | public class JParsingTest {
17 | public static final String urlString = "http://news-at.zhihu.com/api/4/news/latest";
18 | public static void main(String[] args) throws Exception {
19 | long startTime = 0;
20 | try {
21 | String jsonString = new String(HttpUtil.get(urlString));
22 | startTime = System.currentTimeMillis();
23 |
24 | JObject latestNewsJSON = parseJSONObject(jsonString);
25 | String date = latestNewsJSON.getString("date");
26 | JArray top_storiesJSON = latestNewsJSON.getJArray("top_stories");
27 | LatestNews latest = new LatestNews();
28 | List stories = new ArrayList<>();
29 | for (int i = 0; i < top_storiesJSON.length(); i++) {
30 | LatestNews.TopStory story = new LatestNews.TopStory();
31 | story.setId(((JObject) top_storiesJSON.get(i)).getInt("id"));
32 | story.setType(((JObject) top_storiesJSON.get(i)).getInt("type"));
33 | story.setImage(((JObject) top_storiesJSON.get(i)).getString("image"));
34 | story.setTitle(((JObject) top_storiesJSON.get(i)).getString("title"));
35 | stories.add(story);
36 | }
37 |
38 | long endTime = System.currentTimeMillis();
39 | double time = (double) (endTime - startTime) / 1000.0;
40 | System.out.println("took " + time + "seconds.");
41 |
42 | latest.setDate(date);
43 | System.out.println("date: " + latest.getDate());
44 | for (int i = 0; i < stories.size(); i++) {
45 | System.out.println(stories.get(i));
46 | }
47 |
48 | } catch (JSONException e) {
49 | e.printStackTrace();
50 | }
51 |
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/JSONParsingTest.java:
--------------------------------------------------------------------------------
1 | import model.LatestNews;
2 | import org.json.JSONArray;
3 | import org.json.JSONException;
4 | import org.json.JSONObject;
5 | import parser.JArray;
6 | import parser.JObject;
7 | import parser.Parser;
8 |
9 | import java.io.ByteArrayOutputStream;
10 | import java.io.Closeable;
11 | import java.io.IOException;
12 | import java.io.InputStream;
13 | import java.net.HttpURLConnection;
14 | import java.net.URL;
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | /**
19 | * Created by Administrator on 2016/5/17.
20 | */
21 | public class JSONParsingTest {
22 | public static final String urlString = "http://news-at.zhihu.com/api/4/news/latest";
23 | public static void main(String[] args) throws Exception {
24 | long startTime = 0;
25 | try {
26 | String jsonString = new String(HttpUtil.get(urlString));
27 | startTime = System.currentTimeMillis();
28 |
29 | JSONObject latestNewsJSON = new JSONObject(jsonString);
30 | String date = latestNewsJSON.getString("date");
31 | JSONArray top_storiesJSON = latestNewsJSON.getJSONArray("top_stories");
32 | LatestNews latest = new LatestNews();
33 | List stories = new ArrayList<>();
34 | for (int i = 0; i < top_storiesJSON.length(); i++) {
35 | LatestNews.TopStory story = new LatestNews.TopStory();
36 | story.setId(((JSONObject) top_storiesJSON.get(i)).getInt("id"));
37 | story.setType(((JSONObject) top_storiesJSON.get(i)).getInt("type"));
38 | story.setImage(((JSONObject) top_storiesJSON.get(i)).getString("image"));
39 | story.setTitle(((JSONObject) top_storiesJSON.get(i)).getString("title"));
40 | stories.add(story);
41 | }
42 |
43 | long endTime = System.currentTimeMillis();
44 | double time = (double) (endTime - startTime) / 1000.0;
45 | System.out.println("took " + time + "seconds.");
46 |
47 | latest.setDate(date);
48 | System.out.println("date: " + latest.getDate());
49 | for (int i = 0; i < stories.size(); i++) {
50 | System.out.println(stories.get(i));
51 | }
52 |
53 | } catch (JSONException e) {
54 | e.printStackTrace();
55 | }
56 |
57 | }
58 |
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/SimpleJSONTest.java:
--------------------------------------------------------------------------------
1 | import com.google.gson.Gson;
2 | import model.LatestNews;
3 | import parser.Parser;
4 |
5 | /**
6 | * Created by Administrator on 2016/5/22.
7 | */
8 | public class SimpleJSONTest {
9 | public static final String urlString = "http://news-at.zhihu.com/api/4/news/latest";
10 | public static void main(String[] args) throws Exception {
11 | String jsonString = new String(HttpUtil.get(urlString));
12 |
13 | long startTime = System.currentTimeMillis();
14 |
15 | LatestNews latest = Parser.fromJson(jsonString, LatestNews.class);
16 |
17 | long endTime = System.currentTimeMillis();
18 | double time = (double) (endTime - startTime) / 1000.0;
19 | System.out.println("took " + time + "seconds.");
20 |
21 | System.out.println(latest.getDate());
22 | for (int i = 0; i < latest.getTop_stories().size(); i++) {
23 | System.out.println(latest.getTop_stories().get(i));
24 | }
25 | for (int i = 0; i < latest.getStories().size(); i++) {
26 | System.out.println(latest.getStories().get(i));
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/exception/JsonParseException.java:
--------------------------------------------------------------------------------
1 | package exception;
2 |
3 | import java.io.IOException;
4 |
5 | /**
6 | * Created by Administrator on 2016/5/22.
7 | */
8 | public class JsonParseException extends IOException {
9 | public JsonParseException(String msg) {
10 | super(msg);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/model/LatestNews.java:
--------------------------------------------------------------------------------
1 | package model;
2 |
3 | import java.io.Serializable;
4 | import java.util.List;
5 |
6 | /**
7 | * Created by Administrator on 2016/5/17.
8 | */
9 | public class LatestNews {
10 | private String date;
11 | private List top_stories;
12 | private List stories;
13 |
14 |
15 | public void setTopStories(List top_stories) {
16 | this.top_stories = top_stories;
17 | }
18 |
19 | public void setStories(List stories) {
20 | this.stories = stories;
21 | }
22 |
23 | public void setDate(String date) {
24 | this.date = date;
25 | }
26 |
27 | public List getTop_stories() {
28 | return top_stories;
29 | }
30 |
31 | public List getStories() {
32 | return stories;
33 | }
34 |
35 | public String getDate() {
36 | return date;
37 | }
38 |
39 | public static class TopStory {
40 | private String image;
41 | private int type;
42 | private int id;
43 | private String title;
44 |
45 | public void setId(int id) {
46 | this.id = id;
47 | }
48 |
49 | public void setTitle(String title) {
50 | this.title = title;
51 | }
52 |
53 | public void setImage(String image) {
54 | this.image = image;
55 | }
56 |
57 | public void setType(int type) {
58 | this.type = type;
59 | }
60 |
61 | public int getId() {
62 | return id;
63 | }
64 |
65 | public String getTitle() {
66 | return title;
67 | }
68 |
69 | public String getImage() {
70 | return image;
71 | }
72 |
73 | public int getType() {
74 | return type;
75 | }
76 |
77 | public String toString() {
78 | return "id = " + id + ", title = " + title + ", image = " + image + ", type = " + type + "\n";
79 | }
80 |
81 | }
82 |
83 | public static class Story implements Serializable {
84 | private List images;
85 | private int type;
86 | private int id;
87 | private String title;
88 |
89 | public List getImages() {
90 | return images;
91 | }
92 |
93 | public void setImages(List images) {
94 | this.images = images;
95 | }
96 |
97 | public int getType() {
98 | return type;
99 | }
100 |
101 | public void setType(int type) {
102 | this.type = type;
103 | }
104 |
105 | public int getId() {
106 | return id;
107 | }
108 |
109 | public void setId(int id) {
110 | this.id = id;
111 | }
112 |
113 | public String getTitle() {
114 | return title;
115 | }
116 |
117 | public void setTitle(String title) {
118 | this.title = title;
119 | }
120 |
121 | public String toString() {
122 | return "id = " + id + ", title = " + title + ", images = " + images.get(0) + ", type = " + type + "\n";
123 | }
124 |
125 | }
126 |
127 |
128 | }
129 |
130 |
--------------------------------------------------------------------------------
/src/parser/JArray.java:
--------------------------------------------------------------------------------
1 | package parser;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * Created by Administrator on 2016/5/20.
8 | */
9 | public class JArray implements Json, Value {
10 | private List list = new ArrayList<>();
11 |
12 | public JArray(List list) {
13 | this.list = list;
14 | }
15 |
16 | public int length() {
17 | return list.size();
18 | }
19 |
20 | public void add(Json element) {
21 | list.add(element);
22 | }
23 |
24 | public Json get(int i) {
25 | return list.get(i);
26 | }
27 |
28 | public String toString() {
29 | StringBuilder sb = new StringBuilder();
30 | sb.append("[ ");
31 | for (int i =0; i < list.size(); i++) {
32 | sb.append(list.get(i).toString());
33 | if (i != list.size() - 1) {
34 | sb.append(", ");
35 | }
36 | }
37 | sb.append(" ]");
38 | return sb.toString();
39 | }
40 |
41 | @Override
42 | public Object value() {
43 | return this;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/parser/JObject.java:
--------------------------------------------------------------------------------
1 | package parser;
2 |
3 | import java.util.ArrayList;
4 | import java.util.HashMap;
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 | /**
9 | * Created by Administrator on 2016/5/20.
10 | */
11 | public class JObject implements Json {
12 | private Map map = new HashMap<>();
13 |
14 | public JObject(Map map) {
15 | this.map = map;
16 | }
17 |
18 | public int getInt(String key) {
19 | return Integer.parseInt((String) map.get(key).value());
20 | }
21 |
22 | public String getString(String key) {
23 | return (String) map.get(key).value();
24 | }
25 |
26 | public boolean getBoolean(String key) {
27 | return Boolean.parseBoolean((String) map.get(key).value());
28 | }
29 |
30 | public JArray getJArray(String key) {
31 | return (JArray) map.get(key).value();
32 | }
33 |
34 | public String toString() {
35 | StringBuilder sb = new StringBuilder();
36 | sb.append("{ ");
37 | int size = map.size();
38 | for (String key : map.keySet()) {
39 | sb.append(key + " : " + map.get(key));
40 | if (--size != 0) {
41 | sb.append(", ");
42 | }
43 | }
44 | sb.append(" }");
45 | return sb.toString();
46 | }
47 |
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/parser/Json.java:
--------------------------------------------------------------------------------
1 | package parser;
2 |
3 | /**
4 | * Created by Administrator on 2016/5/20.
5 | */
6 | public interface Json {
7 | }
8 |
--------------------------------------------------------------------------------
/src/parser/Key.java:
--------------------------------------------------------------------------------
1 | package parser;
2 |
3 | /**
4 | * Created by Administrator on 2016/5/20.
5 | */
6 | public class Key {
7 | }
8 |
--------------------------------------------------------------------------------
/src/parser/Parser.java:
--------------------------------------------------------------------------------
1 | package parser;
2 |
3 | import com.google.gson.JsonParseException;
4 | import tokenizer.Token;
5 | import tokenizer.TokenType;
6 | import tokenizer.Tokenizer;
7 |
8 | import java.io.*;
9 | import java.lang.reflect.Constructor;
10 | import java.lang.reflect.Field;
11 | import java.lang.reflect.ParameterizedType;
12 | import java.lang.reflect.Type;
13 | import java.util.ArrayList;
14 | import java.util.HashMap;
15 | import java.util.List;
16 | import java.util.Map;
17 |
18 | /**
19 | * Created by Administrator on 2016/5/20.
20 | */
21 | public class Parser {
22 | private Tokenizer tokenizer;
23 |
24 | public Parser(Tokenizer tokenizer) {
25 | this.tokenizer = tokenizer;
26 | }
27 |
28 | private JObject object() {
29 | tokenizer.next(); //consume '{'
30 | Map map = new HashMap<>();
31 | if (isToken(TokenType.END_OBJ)) {
32 | tokenizer.next(); //consume '}'
33 | return new JObject(map);
34 | } else if (isToken(TokenType.STRING)) {
35 | map = key(map);
36 | }
37 | return new JObject(map);
38 | }
39 |
40 | private Map key(Map map) {
41 | String key = tokenizer.next().getValue();
42 | if (!isToken(TokenType.COLON)) {
43 | throw new JsonParseException("Invalid JSON input.");
44 | } else {
45 | tokenizer.next(); //consume ':'
46 | if (isPrimary()) {
47 | Value primary = new Primary(tokenizer.next().getValue());
48 | map.put(key, primary);
49 | } else if (isToken(TokenType.START_ARRAY)) {
50 | Value array = array();
51 | map.put(key, array);
52 | }
53 | if (isToken(TokenType.COMMA)) {
54 | tokenizer.next(); //consume ','
55 | if (isToken(TokenType.STRING)) {
56 | map = key(map);
57 | }
58 | } else if (isToken(TokenType.END_OBJ)) {
59 | tokenizer.next(); //consume '}'
60 | return map;
61 | } else {
62 | throw new JsonParseException("Invalid JSON input.");
63 | }
64 | }
65 | return map;
66 | }
67 |
68 | private JArray array() {
69 | tokenizer.next(); //consume '['
70 | List list = new ArrayList<>();
71 | JArray array = null;
72 | if (isToken(TokenType.START_ARRAY)) {
73 | array = array();
74 | list.add(array);
75 | if (isToken(TokenType.COMMA)) {
76 | tokenizer.next(); //consume ','
77 | list = element(list);
78 | }
79 | } else if (isPrimary()) {
80 | list = element(list);
81 | } else if (isToken(TokenType.START_OBJ)) {
82 | list.add(object());
83 | while (isToken(TokenType.COMMA)) {
84 | tokenizer.next(); //consume ','
85 | list.add(object());
86 | }
87 | } else if (isToken(TokenType.END_ARRAY)) {
88 | tokenizer.next(); //consume ']'
89 | array = new JArray(list);
90 | return array;
91 | }
92 | tokenizer.next(); //consume ']'
93 | array = new JArray(list);
94 | return array;
95 | }
96 |
97 | private List element(List list) {
98 | list.add(new Primary(tokenizer.next().getValue()));
99 | if (isToken(TokenType.COMMA)) {
100 | tokenizer.next(); //consume ','
101 | if (isPrimary()) {
102 | list = element(list);
103 | } else if (isToken(TokenType.START_OBJ)) {
104 | list.add(object());
105 | } else if (isToken(TokenType.START_ARRAY)) {
106 | list.add(array());
107 | } else {
108 | throw new JsonParseException("Invalid JSON input.");
109 | }
110 | } else if (isToken(TokenType.END_ARRAY)) {
111 | return list;
112 | } else {
113 | throw new JsonParseException("Invalid JSON input.");
114 | }
115 | return list;
116 | }
117 |
118 | private Json json() {
119 | TokenType type = tokenizer.peek(0).getType();
120 | if (type == TokenType.START_ARRAY) {
121 | return array();
122 | } else if (type == TokenType.START_OBJ) {
123 | return object();
124 | } else {
125 | throw new JsonParseException("Invalid JSON input.");
126 | }
127 | }
128 |
129 | private boolean isToken(TokenType tokenType) {
130 | Token t = tokenizer.peek(0);
131 | return t.getType() == tokenType;
132 | }
133 |
134 | private boolean isToken(String name) {
135 | Token t = tokenizer.peek(0);
136 | return t.getValue().equals(name);
137 | }
138 |
139 | private boolean isPrimary() {
140 | TokenType type = tokenizer.peek(0).getType();
141 | return type == TokenType.BOOLEAN || type == TokenType.NULL ||
142 | type == TokenType.NUMBER || type == TokenType.STRING;
143 | }
144 |
145 | public Json parse() throws Exception {
146 | Json result = json();
147 | return result;
148 | }
149 |
150 | public static JObject parseJSONObject(String s) throws Exception {
151 | Tokenizer tokenizer = new Tokenizer(new BufferedReader(new StringReader(s)));
152 | tokenizer.tokenize();
153 | Parser parser = new Parser(tokenizer);
154 | return parser.object();
155 | }
156 |
157 | public static JArray parseJSONArray(String s) throws Exception {
158 | Tokenizer tokenizer = new Tokenizer(new BufferedReader(new StringReader(s)));
159 | tokenizer.tokenize();
160 | Parser parser = new Parser(tokenizer);
161 | return parser.array();
162 | }
163 |
164 | public static T fromJson(String jsonString, Class classOfT) throws Exception {
165 | Tokenizer tokenizer = new Tokenizer(new BufferedReader(new StringReader(jsonString)));
166 | tokenizer.tokenize();
167 | Parser parser = new Parser(tokenizer);
168 | JObject result = parser.object();
169 |
170 | Constructor constructor = classOfT.getConstructor();
171 | Object latestNews = constructor.newInstance();
172 | Field[] fields = classOfT.getDeclaredFields();
173 | int numField = fields.length;
174 | String[] fieldNames = new String[numField];
175 | String[] fieldTypes = new String[numField];
176 | for (int i = 0; i < numField; i++) {
177 | String type = fields[i].getType().getTypeName();
178 | String name = fields[i].getName();
179 | fieldTypes[i] = type;
180 | fieldNames[i] = name;
181 | }
182 | for (int i = 0; i < numField; i++) {
183 | if (fieldTypes[i].equals("java.lang.String")) {
184 | fields[i].setAccessible(true);
185 | fields[i].set(latestNews, result.getString(fieldNames[i]));
186 | } else if (fieldTypes[i].equals("java.util.List")) {
187 | fields[i].setAccessible(true);
188 | JArray array = result.getJArray(fieldNames[i]);
189 | ParameterizedType pt = (ParameterizedType) fields[i].getGenericType();
190 | Type elementType = pt.getActualTypeArguments()[0];
191 | String elementTypeName = elementType.getTypeName();
192 | Class> elementClass = Class.forName(elementTypeName);
193 |
194 | fields[i].set(latestNews, inflateList(array, elementClass));//Type Capture
195 |
196 | } else if (fieldTypes[i].equals("int")) {
197 | fields[i].setAccessible(true);
198 | fields[i].set(latestNews, result.getString(fieldNames[i]));
199 | }
200 | }
201 | return (T) latestNews;
202 | }
203 |
204 | public static List inflateList(JArray array, Class clz) throws Exception {
205 | int size = array.length();
206 |
207 | List list = new ArrayList();
208 | Constructor constructor = clz.getConstructor();
209 | String className = clz.getName();
210 | if (className.equals("java.lang.String")) {
211 | for (int i = 0; i < size; i++) {
212 | String element = (String) ((Primary) array.get(i)).value();
213 | list.add((T) element);
214 | return list;
215 | }
216 | }
217 | Field[] fields = clz.getDeclaredFields();
218 | int numField = fields.length;
219 | String[] fieldNames = new String[numField];
220 | String[] fieldTypes = new String[numField];
221 |
222 | for (int i = 0; i < numField; i++) {
223 | String type = fields[i].getType().getTypeName();
224 | String name = fields[i].getName();
225 | fieldTypes[i] = type;
226 | fieldNames[i] = name;
227 | }
228 | for (int i = 0; i < size; i++) {
229 | T element = constructor.newInstance();
230 | JObject object = (JObject) array.get(i);
231 | for (int j = 0; j < numField; j++) {
232 | if (fieldTypes[j].equals("java.lang.String")) {
233 | fields[j].setAccessible(true);
234 | fields[j].set(element, (object.getString(fieldNames[j])));
235 | } else if (fieldTypes[j].equals("java.util.List")) {
236 | fields[j].setAccessible(true);
237 | JArray nestArray = object.getJArray(fieldNames[j]);
238 | ParameterizedType pt = (ParameterizedType) fields[j].getGenericType();
239 | Type elementType = pt.getActualTypeArguments()[0];
240 | String elementTypeName = elementType.getTypeName();
241 | Class> elementClass = Class.forName(elementTypeName);
242 | String value = null;
243 |
244 | fields[j].set(element, inflateList(nestArray, elementClass));//Type Capture
245 | } else if (fieldTypes[j].equals("int")) {
246 | fields[j].setAccessible(true);
247 | fields[j].set(element, object.getInt(fieldNames[j]));
248 | }
249 | }
250 | list.add(element);
251 | }
252 | return list;
253 | }
254 |
255 | }
256 |
--------------------------------------------------------------------------------
/src/parser/Primary.java:
--------------------------------------------------------------------------------
1 | package parser;
2 |
3 | /**
4 | * Created by Administrator on 2016/5/20.
5 | */
6 | public class Primary implements Json, Value {
7 | private String value;
8 |
9 | public Primary(String value) {
10 | this.value = value;
11 | }
12 |
13 | public String getValue() {
14 | return value;
15 | }
16 |
17 | public void setValue(String value) {
18 | this.value = value;
19 | }
20 |
21 | public String toString() {
22 | return value;
23 | }
24 |
25 | @Override
26 | public Object value() {
27 | return value;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/parser/Value.java:
--------------------------------------------------------------------------------
1 | package parser;
2 |
3 | /**
4 | * Created by Administrator on 2016/5/20.
5 | */
6 | public interface Value {
7 | Object value();
8 | }
9 |
--------------------------------------------------------------------------------
/src/tokenizer/Token.java:
--------------------------------------------------------------------------------
1 | package tokenizer;
2 |
3 | /**
4 | * Created by Administrator on 2016/5/17.
5 | */
6 | public class Token {
7 | private TokenType type;
8 | private String value;
9 |
10 | public Token(TokenType type, String value) {
11 | this.type = type;
12 | this.value = value;
13 | }
14 |
15 | public TokenType getType() {
16 | return type;
17 | }
18 |
19 | public void setType(TokenType type) {
20 | this.type = type;
21 | }
22 |
23 | public String getValue() {
24 | return value;
25 | }
26 |
27 | public void setValue(String value) {
28 | this.value = value;
29 | }
30 |
31 | public String toString() {
32 | return getValue();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/tokenizer/TokenType.java:
--------------------------------------------------------------------------------
1 | package tokenizer;
2 |
3 | /**
4 | * Created by Administrator on 2016/5/17.
5 | */
6 | public enum TokenType {
7 | START_OBJ, END_OBJ, START_ARRAY, END_ARRAY, NULL, NUMBER, STRING, BOOLEAN, COLON, COMMA, END_DOC
8 | }
9 |
--------------------------------------------------------------------------------
/src/tokenizer/Tokenizer.java:
--------------------------------------------------------------------------------
1 | package tokenizer;
2 |
3 | import exception.JsonParseException;
4 |
5 | import java.io.*;
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 |
10 | /**
11 | * Created by Administrator on 2016/5/17.
12 | */
13 | public class Tokenizer {
14 | private ArrayList tokens = new ArrayList<>();
15 | private Reader reader;
16 | private boolean isUnread = false;
17 | private int savedChar;
18 | private int c; //recently read char
19 |
20 | public Tokenizer(Reader reader) throws IOException {
21 | this.reader = reader;
22 | }
23 |
24 | public List getTokens() {
25 | return tokens;
26 | }
27 |
28 | public void tokenize() throws Exception {
29 | Token token;
30 | do {
31 | token = start();
32 | tokens.add(token);
33 | } while (token.getType() != TokenType.END_DOC);
34 | }
35 |
36 | private Token start() throws Exception {
37 | c = '?';
38 | Token token = null;
39 | do { //先读一个字符,若为空白符(ASCII码在[0, 20H]上)则接着读,直到刚读的字符非空白符
40 | c = read();
41 | } while (isSpace(c));
42 | if (isNull(c)) {
43 | return new Token(TokenType.NULL, null);
44 | } else if (c == ',') {
45 | return new Token(TokenType.COMMA, ",");
46 | } else if (c == ':') {
47 | return new Token(TokenType.COLON, ":");
48 | } else if (c == '{') {
49 | return new Token(TokenType.START_OBJ, "{");
50 | } else if (c == '[') {
51 | return new Token(TokenType.START_ARRAY, "[");
52 | } else if (c == ']') {
53 | return new Token(TokenType.END_ARRAY, "]");
54 | } else if (c == '}') {
55 | return new Token(TokenType.END_OBJ, "}");
56 | } else if (isTrue(c)) {
57 | return new Token(TokenType.BOOLEAN, "true"); //the value of TRUE is not null
58 | } else if (isFalse(c)) {
59 | return new Token(TokenType.BOOLEAN, "false"); //the value of FALSE is null
60 | } else if (c == '"') {
61 | return readString();
62 | } else if (isNum(c)) {
63 | unread();
64 | return readNum();
65 | } else if (c == -1) {
66 | return new Token(TokenType.END_DOC, "EOF");
67 | } else {
68 | throw new JsonParseException("Invalid JSON input.");
69 | }
70 | }
71 |
72 | private int read() throws IOException {
73 | if (!isUnread) {
74 | int c = reader.read();
75 | savedChar = c;
76 | return c;
77 | } else {
78 | isUnread = false;
79 | return savedChar;
80 | }
81 | }
82 |
83 | private void unread() {
84 | isUnread = true;
85 | }
86 |
87 | private boolean isSpace(int c) {
88 | return c >= 0 && c <= ' ';
89 | }
90 |
91 | private boolean isTrue(int c) throws IOException {
92 | if (c == 't') {
93 | c = read();
94 | if (c == 'r') {
95 | c = read();
96 | if (c == 'u') {
97 | c = read();
98 | if (c == 'e') {
99 | return true;
100 | } else {
101 | throw new JsonParseException("Invalid JSON input.");
102 | }
103 | } else {
104 | throw new JsonParseException("Invalid JSON input.");
105 | }
106 | } else {
107 | throw new JsonParseException("Invalid JSON input.");
108 | }
109 | } else {
110 | return false;
111 | }
112 | }
113 |
114 | private boolean isFalse(int c) throws IOException {
115 | if (c == 'f') {
116 | c = read();
117 | if (c == 'a') {
118 | c = read();
119 | if (c == 'l') {
120 | c = read();
121 | if (c == 's') {
122 | c = read();
123 | if (c == 'e') {
124 | return true;
125 | } else {
126 | throw new JsonParseException("Invalid JSON input.");
127 | }
128 | } else {
129 | throw new JsonParseException("Invalid JSON input.");
130 | }
131 | } else {
132 | throw new JsonParseException("Invalid JSON input.");
133 | }
134 | } else {
135 | throw new JsonParseException("Invalid JSON input.");
136 | }
137 | } else {
138 | return false;
139 | }
140 | }
141 |
142 | private boolean isEscape() throws IOException {
143 | if (c == '\\') {
144 | c = read();
145 | if (c == '"' || c == '\\' || c == '/' || c == 'b' ||
146 | c == 'f' || c == 'n' || c == 't' || c == 'r' || c == 'u') {
147 | return true;
148 | } else {
149 | throw new JsonParseException("Invalid JSON input.");
150 | }
151 | } else {
152 | return false;
153 | }
154 | }
155 |
156 | private boolean isNull(int c) throws IOException {
157 | if (c == 'n') {
158 | c = read();
159 | if (c == 'u') {
160 | c = read();
161 | if (c == 'l') {
162 | c = read();
163 | if (c == 'l') {
164 | return true;
165 | } else {
166 | throw new JsonParseException("Invalid JSON input.");
167 | }
168 | } else {
169 | throw new JsonParseException("Invalid JSON input.");
170 | }
171 | } else {
172 | throw new JsonParseException("Invalid JSON input.");
173 | }
174 | } else {
175 | return false;
176 | }
177 | }
178 |
179 | private boolean isDigit(int c) {
180 | return c >= '0' && c <= '9';
181 | }
182 |
183 | private boolean isDigitOne2Nine(int c){
184 | return c >= '1' && c <= '9';
185 | }
186 |
187 | private boolean isSep(int c) {
188 | return c == '}' || c == ']' || c == ',';
189 | }
190 |
191 | private boolean isNum(int c) {
192 | return isDigit(c) || c == '-';
193 | }
194 |
195 | private Token readString() throws IOException {
196 | StringBuilder sb = new StringBuilder();
197 | while (true) {
198 | c = read();
199 | if (isEscape()) { //判断是否为\", \\, \/, \b, \f, \n, \t, \r.
200 | if (c == 'u') {
201 | sb.append('\\' + (char) c);
202 | for (int i = 0; i < 4; i++) {
203 | c = read();
204 | if (isHex(c)) {
205 | sb.append((char) c);
206 | } else {
207 | throw new JsonParseException("Invalid Json input.");
208 | }
209 | }
210 | } else {
211 | sb.append("\\" + (char) c);
212 | }
213 | } else if (c == '"') {
214 | return new Token(TokenType.STRING, sb.toString());
215 | } else if (c == '\r' || c == '\n'){
216 | throw new JsonParseException("Invalid JSON input.");
217 | } else {
218 | sb.append((char) c);
219 | }
220 | }
221 | }
222 |
223 | private Token readNum() throws IOException {
224 | StringBuilder sb = new StringBuilder();
225 | int c = read();
226 | if (c == '-') { //-
227 | sb.append((char) c);
228 | c = read();
229 | if (c == '0') { //-0
230 | sb.append((char) c);
231 | numAppend(sb);
232 |
233 | } else if (isDigitOne2Nine(c)) { //-digit1-9
234 | do {
235 | sb.append((char) c);
236 | c = read();
237 | } while (isDigit(c));
238 | unread();
239 | numAppend(sb);
240 | } else {
241 | throw new JsonParseException("- not followed by digit");
242 | }
243 | } else if (c == '0') { //0
244 | sb.append((char) c);
245 | numAppend(sb);
246 | } else if (isDigitOne2Nine(c)) { //digit1-9
247 | do {
248 | sb.append((char) c);
249 | c = read();
250 | } while (isDigit(c));
251 | unread();
252 | numAppend(sb);
253 | }
254 | return new Token(TokenType.NUMBER, sb.toString()); //the value of 0 is null
255 | }
256 |
257 | private void appendFrac(StringBuilder sb) throws IOException {
258 | c = read();
259 | while (isDigit(c)) {
260 | sb.append((char) c);
261 | c = read();
262 | }
263 | }
264 |
265 | private void appendExp(StringBuilder sb) throws IOException {
266 | int c = read();
267 | if (c == '+' || c == '-') {
268 | sb.append((char) c); //append '+' or '-'
269 | c = read();
270 | if (!isDigit(c)) {
271 | throw new JsonParseException("e+(-) or E+(-) not followed by digit");
272 | } else { //e+(-) digit
273 | do {
274 | sb.append((char) c);
275 | c = read();
276 | } while (isDigit(c));
277 | unread();
278 | }
279 | } else if (!isDigit(c)) {
280 | throw new JsonParseException("e or E not followed by + or - or digit.");
281 | } else { //e digit
282 | do {
283 | sb.append((char) c);
284 | c = read();
285 | } while (isDigit(c));
286 | unread();
287 | }
288 | }
289 |
290 | private void numAppend(StringBuilder sb) throws IOException {
291 | c = read();
292 | if (c == '.') { //int frac
293 | sb.append((char) c); //apppend '.'
294 | appendFrac(sb);
295 | if (isExp(c)) { //int frac exp
296 | sb.append((char) c); //append 'e' or 'E';
297 | appendExp(sb);
298 | }
299 |
300 | } else if (isExp(c)) { // int exp
301 | sb.append((char) c); //append 'e' or 'E'
302 | appendExp(sb);
303 | } else {
304 | unread();
305 | }
306 | }
307 |
308 | private boolean isHex(int c) {
309 | return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
310 | (c >= 'A' && c <= 'F');
311 | }
312 |
313 | private boolean isExp(int c) throws IOException {
314 | return c == 'e' || c == 'E';
315 | }
316 |
317 | public Token next() {
318 | return tokens.remove(0);
319 | }
320 |
321 | public Token peek(int i) {
322 | return tokens.get(i);
323 | }
324 |
325 | public boolean hasNext() {
326 | return tokens.get(0).getType() != TokenType.END_DOC;
327 | }
328 |
329 | }
330 |
--------------------------------------------------------------------------------