001package Torello.JSON; 002 003import Torello.JavaDoc.Annotations.IntoHTMLTable; 004import static Torello.JavaDoc.Annotations.IntoHTMLTable.Background.GreenDither; 005import static Torello.JavaDoc.Annotations.IntoHTMLTable.Background.BlueDither; 006 007import java.util.function.Predicate; 008import java.util.function.ToIntFunction; 009import java.util.function.ToLongFunction; 010import java.util.function.ToDoubleFunction; 011 012import Torello.Java.Function.ToByteFunction; 013import Torello.Java.Function.ToShortFunction; 014import Torello.Java.Function.ToFloatFunction; 015 016import javax.json.JsonObject; 017import javax.json.JsonArray; 018import javax.json.JsonString; 019import javax.json.JsonValue; 020 021import static javax.json.JsonValue.ValueType.STRING; 022import static javax.json.JsonValue.ValueType.NULL; 023 024/** 025 * Builds on the J2EE Standard Release JSON Parsing Tools by providing additional 026 * help with converting JSON Data into <B STYLE='color: red'>Java Primitive-Types</B> 027 * 028 * <EMBED CLASS='external-html' DATA-FILE-ID=ALL_CLASSES_NOTE> 029 * <EMBED CLASS='external-html' DATA-FILE-ID=PARSE_PRIM_JSON> 030 * <EMBED CLASS='external-html' DATA-FILE-ID=PARSE_PRIM_PTABLE> 031 * <EMBED CLASS='external-html' DATA-CH=char DATA-FILE-ID=JAVA_LANG_CHAR> 032 * 033 * @see JsonObject 034 * @see JsonArray 035 */ 036@Torello.JavaDoc.Annotations.StaticFunctional 037public class ParsePrimJSON 038{ 039 // This is a static class. Has no program state. 040 private ParsePrimJSON() { } 041 042 043 // ******************************************************************************************** 044 // ******************************************************************************************** 045 // int 046 // ******************************************************************************************** 047 // ******************************************************************************************** 048 049 050 /** <EMBED CLASS='external-html' DATA-JTYPE=int DATA-FILE-ID=PARSE_PRIM_JA> */ 051 @IntoHTMLTable( 052 title="Extract a JsonString from a JsonArray, and Parse into a Java 'int' Primitive", 053 background=BlueDither 054 ) 055 public static int parseInt( 056 final JsonArray ja, 057 final int index, 058 final ToIntFunction<String> optionalUserParser 059 ) 060 { 061 final JsonString js = GET(ja, index, int.class); 062 063 try 064 { 065 return (optionalUserParser != null) 066 ? optionalUserParser.applyAsInt(js.getString()) 067 : Integer.parseInt(js.getString().trim()); 068 } 069 070 catch (Exception e) 071 { throw new JsonStrParseArrException(e, ja, index, js, int.class); } 072 } 073 074 /** <EMBED CLASS='external-html' DATA-JTYPE=long DATA-FILE-ID=PARSE_PRIM_JA> */ 075 @IntoHTMLTable( 076 title="Extract a JsonString from a JsonArray, and Parse into a Java 'long' Primitive", 077 background=GreenDither 078 ) 079 public static long parseLong( 080 final JsonArray ja, 081 final int index, 082 final ToLongFunction<String> optionalUserParser 083 ) 084 { 085 final JsonString js = GET(ja, index, long.class); 086 087 try 088 { 089 return (optionalUserParser != null) 090 ? optionalUserParser.applyAsLong(js.getString()) 091 : Long.parseLong(js.getString().trim()); 092 } 093 094 catch (Exception e) 095 { throw new JsonStrParseArrException(e, ja, index, js, long.class); } 096 } 097 098 /** <EMBED CLASS='external-html' DATA-JTYPE=short DATA-FILE-ID=PARSE_PRIM_JA> */ 099 @IntoHTMLTable( 100 title="Extract a JsonString from a JsonArray, and Parse into a Java 'short' Primitive", 101 background=BlueDither 102 ) 103 public static short parseShort( 104 final JsonArray ja, 105 final int index, 106 final ToShortFunction<String> optionalUserParser 107 ) 108 { 109 final JsonString js = GET(ja, index, short.class); 110 111 try 112 { 113 return (optionalUserParser != null) 114 ? optionalUserParser.applyAsShort(js.getString()) 115 : Short.parseShort(js.getString().trim()); 116 } 117 118 catch (Exception e) 119 { throw new JsonStrParseArrException(e, ja, index, js, short.class); } 120 } 121 122 /** <EMBED CLASS='external-html' DATA-JTYPE=byte DATA-FILE-ID=PARSE_PRIM_JA> */ 123 @IntoHTMLTable( 124 title="Extract a JsonString from a JsonArray, and Parse into a Java 'byte' Primitive", 125 background=GreenDither 126 ) 127 public static byte parseByte( 128 final JsonArray ja, 129 final int index, 130 final ToByteFunction<String> optionalUserParser 131 ) 132 { 133 final JsonString js = GET(ja, index, byte.class); 134 135 try 136 { 137 return (optionalUserParser != null) 138 ? optionalUserParser.applyAsByte(js.getString()) 139 : Byte.parseByte(js.getString().trim()); 140 } 141 142 catch (Exception e) 143 { throw new JsonStrParseArrException(e, ja, index, js, byte.class); } 144 } 145 146 /** <EMBED CLASS='external-html' DATA-JTYPE=double DATA-FILE-ID=PARSE_PRIM_JA> */ 147 @IntoHTMLTable( 148 title="Extract a JsonString from a JsonArray, and Parse into a Java 'double' Primitive", 149 background=BlueDither 150 ) 151 public static double parseDouble( 152 final JsonArray ja, 153 final int index, 154 final ToDoubleFunction<String> optionalUserParser 155 ) 156 { 157 final JsonString js = GET(ja, index, double.class); 158 159 try 160 { 161 return (optionalUserParser != null) 162 ? optionalUserParser.applyAsDouble(js.getString()) 163 : Double.parseDouble(js.getString().trim()); 164 } 165 166 catch (Exception e) 167 { throw new JsonStrParseArrException(e, ja, index, js, double.class); } 168 } 169 170 /** <EMBED CLASS='external-html' DATA-JTYPE=float DATA-FILE-ID=PARSE_PRIM_JA> */ 171 @IntoHTMLTable( 172 title="Extract a JsonString from a JsonArray, and Parse into a Java 'float' Primitive", 173 background=GreenDither 174 ) 175 public static float parseFloat( 176 final JsonArray ja, 177 final int index, 178 final ToFloatFunction<String> optionalUserParser 179 ) 180 { 181 final JsonString js = GET(ja, index, float.class); 182 183 try 184 { 185 return (optionalUserParser != null) 186 ? optionalUserParser.applyAsFloat(js.getString()) 187 : Float.parseFloat(js.getString().trim()); 188 } 189 190 catch (Exception e) 191 { throw new JsonStrParseArrException(e, ja, index, js, float.class); } 192 } 193 194 /** <EMBED CLASS='external-html' DATA-JTYPE=boolean DATA-FILE-ID=PARSE_PRIM_JA> */ 195 @IntoHTMLTable( 196 title="Extract a JsonString from a JsonArray, and Parse into a Java 'boolean' Primitive", 197 background=BlueDither 198 ) 199 public static boolean parseBoolean( 200 final JsonArray ja, 201 final int index, 202 final Predicate<String> optionalUserParser 203 ) 204 { 205 final JsonString js = GET(ja, index, boolean.class); 206 207 try 208 { 209 return (optionalUserParser != null) 210 ? optionalUserParser.test(js.getString()) 211 : Boolean.parseBoolean(js.getString().trim()); 212 } 213 214 catch (Exception e) 215 { throw new JsonStrParseArrException(e, ja, index, js, boolean.class); } 216 } 217 218 219 // ******************************************************************************************** 220 // ******************************************************************************************** 221 // The Internal Methods 222 // ******************************************************************************************** 223 // ******************************************************************************************** 224 225 226 /** 227 * This is an internal helper method for retrieving an element from a {@link JsonArray}, 228 * and converting it to one of the standard <B STYLE='color: red;'>Java Types</B>. 229 * 230 * @param ja Any instance of {@link JsonArray} 231 * @param index Any index into the array which holds a {@link JsonString} 232 * @param primitiveClass Expected Primitive Class, to be returned by caller method 233 * 234 * @return The extracted {@link JsonString}. 235 * 236 * @throws JsonNullPrimitiveArrException If the array element at {@code 'index'} contains 237 * <B STYLE='color: red'>Json-Null</B> 238 * @throws JsonTypeArrException If the array element at {@code 'index'} doesn't contain 239 * {@link JsonString} 240 * @throws IndexOutOfBoundsException If {@code 'index'} is out of the bounds of {@code 'ja'} 241 * 242 * @see #parseInt(JsonArray, int, ToIntFunction) 243 * @see #parseLong(JsonArray, int, ToLongFunction) 244 * @see #parseShort(JsonArray, int, ToShortFunction) 245 * @see #parseByte(JsonArray, int, ToByteFunction) 246 * @see #parseDouble(JsonArray, int, ToDoubleFunction) 247 * @see #parseFloat(JsonArray, int, ToFloatFunction) 248 */ 249 protected static <T> JsonString GET( 250 final JsonArray ja, 251 final int index, 252 final Class<T> primitiveClass 253 ) 254 { 255 // This will throw an IndexOutOfBoundsException if the index is out of bounds. 256 final JsonValue jv = ja.get(index); 257 258 switch (jv.getValueType()) 259 { 260 // This particular Array-Location (the one specified by 'index') contained an actual 261 // 'null' in its place. Primitives cannot be assinged null, but fortunately there is 262 // a JsonException descendant class that handles this exact situation. 263 264 case NULL: throw new JsonNullPrimitiveArrException 265 (ja, index, STRING, primitiveClass); 266 267 case STRING: return (JsonString) jv; 268 269 // The JsonValue at the specified array-index does not contain a JsonString. 270 default: throw new JsonTypeArrException 271 (ja, index, STRING, jv, primitiveClass); 272 } 273 } 274 275 276 // ******************************************************************************************** 277 // ******************************************************************************************** 278 // int 279 // ******************************************************************************************** 280 // ******************************************************************************************** 281 282 283 /** <EMBED CLASS='external-html' DATA-JTYPE=int DATA-FILE-ID=PARSE_PRIM_JO> */ 284 @IntoHTMLTable( 285 title="Extract a JsonString from a JsonObject, and Parse into a Java 'int' Primitive", 286 background=BlueDither 287 ) 288 public static int parseInt( 289 final JsonObject jo, 290 final String propertyName, 291 final ToIntFunction<String> optionalUserParser 292 ) 293 { 294 final JsonString js = GET(jo, propertyName, int.class); 295 296 try 297 { 298 return (optionalUserParser != null) 299 ? optionalUserParser.applyAsInt(js.getString()) 300 : Integer.parseInt(js.getString().trim()); 301 } 302 303 catch (Exception e) 304 { throw new JsonStrParseObjException(e, jo, propertyName, js, int.class); } 305 } 306 307 /** <EMBED CLASS='external-html' DATA-JTYPE=long DATA-FILE-ID=PARSE_PRIM_JO> */ 308 @IntoHTMLTable( 309 title="Extract a JsonString from a JsonObject, and Parse into a Java 'long' Primitive", 310 background=GreenDither 311 ) 312 public static long parseLong( 313 final JsonObject jo, 314 final String propertyName, 315 final ToLongFunction<String> optionalUserParser 316 ) 317 { 318 final JsonString js = GET(jo, propertyName, long.class); 319 320 try 321 { 322 return (optionalUserParser != null) 323 ? optionalUserParser.applyAsLong(js.getString()) 324 : Long.parseLong(js.getString().trim()); 325 } 326 327 catch (Exception e) 328 { throw new JsonStrParseObjException(e, jo, propertyName, js, long.class); } 329 } 330 331 /** <EMBED CLASS='external-html' DATA-JTYPE=short DATA-FILE-ID=PARSE_PRIM_JO> */ 332 @IntoHTMLTable( 333 title="Extract a JsonString from a JsonObject, and Parse into a Java 'short' Primitive", 334 background=BlueDither 335 ) 336 public static short parseShort( 337 final JsonObject jo, 338 final String propertyName, 339 final ToShortFunction<String> optionalUserParser 340 ) 341 { 342 final JsonString js = GET(jo, propertyName, short.class); 343 344 try 345 { 346 return (optionalUserParser != null) 347 ? optionalUserParser.applyAsShort(js.getString()) 348 : Short.parseShort(js.getString().trim()); 349 } 350 351 catch (Exception e) 352 { throw new JsonStrParseObjException(e, jo, propertyName, js, short.class); } 353 } 354 355 /** <EMBED CLASS='external-html' DATA-JTYPE=byte DATA-FILE-ID=PARSE_PRIM_JO> */ 356 @IntoHTMLTable( 357 title="Extract a JsonString from a JsonObject, and Parse into a Java 'byte' Primitive", 358 background=GreenDither 359 ) 360 public static byte parseByte( 361 final JsonObject jo, 362 final String propertyName, 363 final ToByteFunction<String> optionalUserParser 364 ) 365 { 366 final JsonString js = GET(jo, propertyName, byte.class); 367 368 try 369 { 370 return (optionalUserParser != null) 371 ? optionalUserParser.applyAsByte(js.getString()) 372 : Byte.parseByte(js.getString().trim()); 373 } 374 375 catch (Exception e) 376 { throw new JsonStrParseObjException(e, jo, propertyName, js, byte.class); } 377 } 378 379 /** <EMBED CLASS='external-html' DATA-JTYPE=double DATA-FILE-ID=PARSE_PRIM_JO> */ 380 @IntoHTMLTable( 381 title="Extract a JsonString from a JsonObject, and Parse into a Java 'double' Primitive", 382 background=BlueDither 383 ) 384 public static double parseDouble( 385 final JsonObject jo, 386 final String propertyName, 387 final ToDoubleFunction<String> optionalUserParser 388 ) 389 { 390 final JsonString js = GET(jo, propertyName, double.class); 391 392 try 393 { 394 return (optionalUserParser != null) 395 ? optionalUserParser.applyAsDouble(js.getString()) 396 : Double.parseDouble(js.getString().trim()); 397 } 398 399 catch (Exception e) 400 { throw new JsonStrParseObjException(e, jo, propertyName, js, double.class); } 401 } 402 403 /** <EMBED CLASS='external-html' DATA-JTYPE=float DATA-FILE-ID=PARSE_PRIM_JO> */ 404 @IntoHTMLTable( 405 title="Extract a JsonString from a JsonObject, and Parse into a Java 'float' Primitive", 406 background=GreenDither 407 ) 408 public static float parseFloat( 409 final JsonObject jo, 410 final String propertyName, 411 final ToFloatFunction<String> optionalUserParser 412 ) 413 { 414 final JsonString js = GET(jo, propertyName, float.class); 415 416 try 417 { 418 return (optionalUserParser != null) 419 ? optionalUserParser.applyAsFloat(js.getString()) 420 : Float.parseFloat(js.getString().trim()); 421 } 422 423 catch (Exception e) 424 { throw new JsonStrParseObjException(e, jo, propertyName, js, float.class); } 425 } 426 427 /** <EMBED CLASS='external-html' DATA-JTYPE=boolean DATA-FILE-ID=PARSE_PRIM_JO> */ 428 @IntoHTMLTable( 429 title="Extract a JsonString from a JsonObject, and Parse into a Java 'boolean' Primitive", 430 background=BlueDither 431 ) 432 public static boolean parseBoolean( 433 final JsonObject jo, 434 final String propertyName, 435 final Predicate<String> optionalUserParser 436 ) 437 { 438 final JsonString js = GET(jo, propertyName, boolean.class); 439 440 try 441 { 442 return (optionalUserParser != null) 443 ? optionalUserParser.test(js.getString()) 444 : Boolean.parseBoolean(js.getString().trim()); 445 } 446 447 catch (Exception e) 448 { throw new JsonStrParseObjException(e, jo, propertyName, js, boolean.class); } 449 } 450 451 452 // ******************************************************************************************** 453 // ******************************************************************************************** 454 // The Internal Methods 455 // ******************************************************************************************** 456 // ******************************************************************************************** 457 458 459 /** 460 * This is an internal helper method for retrieving a property from a {@link JsonObject}, 461 * and converting it to one of the standard <B STYLE='color: red;'>Java Types</B>. 462 * 463 * @param jo Any instance of {@link JsonObject} 464 * @param propertyName Any property name contained by {@code 'jo'}, having a {@link JsonString} 465 * @param primitiveClass Expected Primitive Class, to be returned by caller method 466 * 467 * @return The extracted {@link JsonString}. 468 * 469 * @throws JsonNullPrimitiveObjException If the specified property contains 470 * <B STYLE='color: red'>Json-Null</B> 471 * @throws JsonTypeObjException If the specified property doesn't contain 472 * {@link JsonString} 473 * @throws JsonPropMissingException If the property is missing. 474 * 475 * @see #parseInt(JsonObject, String, ToIntFunction) 476 * @see #parseLong(JsonObject, String, ToLongFunction) 477 * @see #parseShort(JsonObject, String, ToShortFunction) 478 * @see #parseByte(JsonObject, String, ToByteFunction) 479 * @see #parseDouble(JsonObject, String, ToDoubleFunction) 480 * @see #parseFloat(JsonObject, String, ToFloatFunction) 481 */ 482 protected static <T> JsonString GET( 483 final JsonObject jo, 484 final String propertyName, 485 final Class<T> primitiveClass 486 ) 487 { 488 // Here, a 'get' request was made for a property that isn't actually listed among the 489 // properties in the provided JsonObject. Since this internal 'GET' is used by methods 490 // that are trying to return a Java Primitive (like 'int' or 'float'), then an exception 491 // has to be thrown. The option of returning 'null' isn't possible here! 492 493 if (! jo.containsKey(propertyName)) throw new JsonPropMissingException 494 (jo, propertyName, STRING, primitiveClass); 495 496 final JsonValue jv = jo.get(propertyName); 497 498 switch (jv.getValueType()) 499 { 500 // A Json-"null" was listed as the "value" assigned to this property 501 // Primitive's cannot encode "null." Fortunately, there is a specialized Java-HTML 502 // JsonException sub-class that handles exactly this type of situation. 503 // 504 // "someJsonObjectPropert": null, 505 506 case NULL: throw new JsonNullPrimitiveObjException 507 (jo, propertyName, STRING, primitiveClass); 508 509 case STRING: return (JsonString) jv; 510 511 // The JsonObject property does not contain a JsonString. 512 default: throw new JsonTypeObjException 513 (jo, propertyName, STRING, jv, primitiveClass); 514 } 515 } 516 517}