├── .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 | --------------------------------------------------------------------------------