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 */