001/*
002MIT License
003
004Copyright (c) 2020 FBSQL Team
005
006Permission is hereby granted, free of charge, to any person obtaining a copy
007of this software and associated documentation files (the "Software"), to deal
008in the Software without restriction, including without limitation the rights
009to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
010copies of the Software, and to permit persons to whom the Software is
011furnished to do so, subject to the following conditions:
012
013The above copyright notice and this permission notice shall be included in all
014copies or substantial portions of the Software.
015
016THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
017IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
018FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
019AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
020LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
021OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
022SOFTWARE.
023
024Home:   https://fbsql.github.io
025E-Mail: fbsql.team@gmail.com
026*/
027
028package org.fbsql.json.parser;
029
030import java.util.ArrayList;
031import java.util.LinkedHashMap;
032import java.util.List;
033import java.util.Map;
034
035public class JsonUtils {
036
037        /**
038         * Parse JSON float
039         *
040         * @param s - character sequence to parse
041         * @return
042         */
043        @SuppressWarnings("unchecked")
044        public static Map<String, String> parseJsonObject(CharSequence cs) {
045                return (Map<String, String>) parseJson(cs);
046        }
047
048        /**
049         * Parse JSON attay
050         *
051         * @param s - character sequence to parse
052         * @return
053         */
054        @SuppressWarnings("unchecked")
055        public static List<String> parseJsonArray(CharSequence s) {
056                return (List<String>) parseJson(s);
057        }
058
059        /**
060         * Parse JSON String
061         *
062         * @param s - character sequence to parse
063         * @return
064         */
065        public static String parseJsonString(CharSequence s) {
066                return (String) parseJson(s);
067        }
068
069        /**
070         * 
071         * @param s
072         * @return
073         */
074        public static boolean parseJsonBoolean(CharSequence s) {
075                return (Boolean) parseJson(s);
076        }
077
078        /**
079         * Parse JSON number
080         *
081         * @param s - character sequence to parse
082         * @return
083         */
084        public static Number parseJsonNumber(CharSequence s) {
085                return (Number) parseJson(s);
086        }
087
088        /**
089         * Parse JSON short
090         *
091         * @param s - character sequence to parse
092         * @return
093         */
094        public static Short parseJsonShort(CharSequence s) {
095                Number number = parseJsonNumber(s);
096                if (number == null)
097                        return null;
098                return number.shortValue();
099        }
100
101        /**
102         * Parse JSON integer
103         *
104         * @param s - character sequence to parse
105         * @return
106         */
107        public static Integer parseJsonInt(CharSequence s) {
108                Number number = parseJsonNumber(s);
109                if (number == null)
110                        return null;
111                return number.intValue();
112        }
113
114        /**
115         * Parse JSON long
116         *
117         * @param s - character sequence to parse
118         * @return
119         */
120        public static Long parseJsonLong(CharSequence s) {
121                Number number = parseJsonNumber(s);
122                if (number == null)
123                        return null;
124                return number.longValue();
125        }
126
127        /**
128         * Parse JSON double
129         *
130         * @param s - character sequence to parse
131         * @return
132         */
133        public static Double parseJsonDouble(CharSequence s) {
134                Number number = parseJsonNumber(s);
135                if (number == null)
136                        return null;
137                return number.doubleValue();
138        }
139
140        /**
141         * Parse JSON float
142         *
143         * @param s - character sequence to parse
144         * @return
145         */
146        public static Float parseJsonFloat(CharSequence s) {
147                Number number = parseJsonNumber(s);
148                if (number == null)
149                        return null;
150                return number.floatValue();
151        }
152
153        /**
154         * Parse JSON null
155         *
156         * @param s - character sequence to parse
157         * @return
158         */
159        public Object parseJsonNull(CharSequence s) {
160                return parseJson(s);
161        }
162
163        /**
164         * Parse JSON object
165         *
166         * @param cs - character sequence to parse
167         * @return   - Object
168         */
169        public static Object parseJson(CharSequence cs) {
170                String s = cs.toString();
171                s = s.trim();
172                char c1 = s.charAt(0);
173                char c2 = s.charAt(s.length() - 1);
174                if (c1 == '{' && c2 == '}')
175                        return parseObject(cut(s));
176                else if (c1 == '[' && c2 == ']')
177                        return parseArray(cut(s));
178                else if (c1 == '\"' && c2 == '\"')
179                        return parseString(cut(s));
180                else if ("true".equals(s))
181                        return true;
182                else if ("false".equals(s))
183                        return false;
184                else if ("null".equals(s))
185                        return null;
186                else if (s.contains("."))
187                        return Double.parseDouble(s);
188                else
189                        return Long.parseLong(s);
190        }
191
192        /**
193         * Parse JSON string
194         *
195         * @param s - character sequence to parse
196         * @return  - string
197         */
198        private static String parseString(CharSequence s) {
199                StringBuilder sb = new StringBuilder();
200                for (int i = 0; i < s.length(); i++) {
201                        char c = s.charAt(i);
202                        if (c != '\\')
203                                sb.append(c);
204                }
205                return sb.toString();
206        }
207
208        /**
209         * Parse JSON array to list of strings
210         *
211         * @param s - character sequence to parse
212         * @return  - list of strings
213         */
214        private static List<String> parseArray(CharSequence s) {
215                return parseSeparated(s, ',');
216        }
217
218        /**
219         * Parse JSON object to map of strings
220         *
221         * @param s - character sequence to parse
222         * @return  - map of strings
223         */
224        private static Map<String, String> parseObject(CharSequence s) {
225                Map<String, String> map = new LinkedHashMap<String, String>();
226                List<String> keyValuesStrs = parseSeparated(s, ',');
227                for (String keyValueStr : keyValuesStrs) {
228                        List<String> keyValue = parseSeparated(keyValueStr, ':');
229                        String dirtyKey = keyValue.get(0);
230                        String key = cut(dirtyKey);
231                        String value = keyValue.get(1);
232                        map.put(key, value);
233                }
234                return map;
235        }
236
237        /**
238         * Trim first and last characters
239         *
240         * @param s - character sequence to process
241         * @return  - trimmed string
242         */
243        private static String cut(CharSequence s) {
244                return s.subSequence(1, s.length() - 1).toString();
245        }
246
247        /**
248         * Parse character sequence separated by particular separator
249         * into list of tokens
250         *
251         * @param s         - character sequence to parse
252         * @param separator - separator
253         * @return          - list of tokens
254         */
255        private static List<String> parseSeparated(CharSequence s, char separator) {
256                List<String> list = new ArrayList<String>();
257                boolean string = false;
258                int array = 0;
259                int object = 0;
260                StringBuilder sb = new StringBuilder();
261                for (int i = 0; i < s.length(); i++) {
262                        char c = s.charAt(i);
263                        //
264                        if (string) {
265                                if (c == '"') {
266                                        char cPrev = s.charAt(i - 1);
267                                        if (cPrev == '"')
268                                                string = false;
269                                        else if (cPrev != '\\')
270                                                string = false;
271                                }
272                        } else {
273                                if (c == '"')
274                                        string = true;
275                        }
276                        //
277                        if (!string) {
278                                if (c == '[')
279                                        array++;
280                                else if (c == ']')
281                                        array--;
282                                else if (c == '{')
283                                        object++;
284                                else if (c == '}')
285                                        object--;
286                        }
287                        //
288                        if (i == s.length() - 1) {
289                                sb.append(c);
290                                list.add(sb.toString().trim());
291                        } else {
292                                if (c == separator && !string && array == 0 && object == 0) {
293                                        list.add(sb.toString().trim());
294                                        sb = new StringBuilder();
295                                } else
296                                        sb.append(c);
297                        }
298                }
299                return list;
300        }
301}
302
303/*
304Please contact FBSQL Team by E-Mail fbsql.team@gmail.com
305or visit https://fbsql.github.io if you need additional
306information or have any questions.
307*/
308
309/* EOF */