001package Torello.JSON; 002 003import Torello.JavaDoc.Annotations.IntoHTMLTable; 004import static Torello.JavaDoc.Annotations.IntoHTMLTable.Background.BlueDither; 005import static Torello.JavaDoc.Annotations.IntoHTMLTable.Background.GreenDither; 006 007import static Torello.JSON.JFlag.*; 008import static Torello.JSON.RJInternal.*; 009import static javax.json.JsonValue.ValueType.*; 010 011import javax.json.JsonObject; 012import javax.json.JsonArray; 013import javax.json.JsonString; 014import javax.json.JsonNumber; 015import javax.json.JsonValue; 016 017import java.math.BigDecimal; 018import java.util.function.Function; 019 020/** 021 * Builds on the J2EE Standard Release JSON Parsing Tools by providing additional 022 * help with converting JSON Data into <B STYLE='color: red'>Java Boxed-Primitive Types</B> 023 * 024 * <EMBED CLASS='external-html' DATA-FILE-ID=ALL_CLASSES_NOTE> 025 * <EMBED CLASS='external-html' DATA-FILE-ID=PARSE_BOXED_JSON> 026 * <EMBED CLASS='external-html' DATA-FILE-ID=PARSE_BOXED_PTABLE> 027 * <EMBED CLASS='external-html' DATA-CH='java.lang.Character' DATA-FILE-ID=JAVA_LANG_CHAR> 028 * 029 * @see JsonObject 030 * @see JsonArray 031 */ 032@Torello.JavaDoc.Annotations.StaticFunctional 033public class ParseBoxedJSON 034{ 035 private ParseBoxedJSON() { } 036 037 038 // ******************************************************************************************** 039 // ******************************************************************************************** 040 // Parse from a JsonArray, into a Boxed-Primitive. ACCEPT USER ERROR-CONTROl FLAGS 041 // ******************************************************************************************** 042 // ******************************************************************************************** 043 044 045 /** 046 * <EMBED CLASS='external-html' DATA-TYPE=Integer DATA-FILE-ID=PARSE_BOXED_WF_JA> 047 * @see #PARSE(JsonArray, int, int, Number, Class, Function, Function, Function) 048 */ 049 @IntoHTMLTable( 050 title="Retrieve a JsonString from a JsonArray index, and parse to a Boxed-Integer", 051 background=BlueDither 052 ) 053 public static Integer parseInteger( 054 final JsonArray ja, 055 final int index, 056 final int FLAGS, 057 final int defaultValue, 058 final Function<String, Integer> optionalParser 059 ) 060 { 061 return PARSE( 062 ja, index, FLAGS, defaultValue, Integer.class, optionalParser, 063 BigDecimal::intValueExact, BigDecimal::intValue 064 ); 065 } 066 067 /** 068 * <EMBED CLASS='external-html' DATA-TYPE=Long DATA-FILE-ID=PARSE_BOXED_WF_JA> 069 * @see #PARSE(JsonArray, int, int, Number, Class, Function, Function, Function) 070 */ 071 @IntoHTMLTable( 072 title= "Retrieve a JsonString from a JsonArray index, and parse to a Boxed Long " + 073 "Integer", 074 background=GreenDither 075 ) 076 public static Long parseLong( 077 final JsonArray ja, 078 final int index, 079 final int FLAGS, 080 final long defaultValue, 081 final Function<String, Long> optionalParser 082 ) 083 { 084 return PARSE( 085 ja, index, FLAGS, defaultValue, Long.class, optionalParser, 086 BigDecimal::longValueExact, BigDecimal::longValue 087 ); 088 } 089 090 /** 091 * <EMBED CLASS='external-html' DATA-TYPE=Integer DATA-FILE-ID=PARSE_BOXED_WF_JA> 092 * @see #PARSE(JsonArray, int, int, Number, Class, Function, Function, Function) 093 */ 094 @IntoHTMLTable( 095 title= "Retrieve a JsonString from a JsonArray index, and parse to a Boxed Short " + 096 "Integer", 097 background=BlueDither 098 ) 099 public static Short parseShort( 100 final JsonArray ja, 101 final int index, 102 final int FLAGS, 103 final short defaultValue, 104 final Function<String, Short> optionalParser 105 ) 106 { 107 return PARSE( 108 ja, index, FLAGS, defaultValue, Short.class, optionalParser, 109 BigDecimal::shortValueExact, BigDecimal::shortValue 110 ); 111 } 112 113 /** 114 * <EMBED CLASS='external-html' DATA-TYPE=Integer DATA-FILE-ID=PARSE_BOXED_WF_JA> 115 * @see #PARSE(JsonArray, int, int, Number, Class, Function, Function, Function) 116 */ 117 @IntoHTMLTable( 118 title="Retrieve a JsonString from a JsonArray index, and parse to a Boxed-Byte", 119 background=GreenDither 120 ) 121 public static Byte parseByte( 122 final JsonArray ja, 123 final int index, 124 final int FLAGS, 125 final byte defaultValue, 126 Function<String, Byte> optionalParser 127 ) 128 { 129 return PARSE( 130 ja, index, FLAGS, defaultValue, Byte.class, optionalParser, 131 BigDecimal::byteValueExact, BigDecimal::byteValue 132 ); 133 } 134 135 /** 136 * <EMBED CLASS='external-html' DATA-TYPE=Integer DATA-FILE-ID=PARSE_BOXED_WF_JA> 137 * @see #PARSE(JsonArray, int, int, Number, Class, Function, Function, Function) 138 */ 139 @IntoHTMLTable( 140 title="Retrieve a JsonString from a JsonArray index, and parse to a Boxed-Double", 141 background=BlueDither 142 ) 143 public static Double parseDouble( 144 final JsonArray ja, 145 final int index, 146 final int FLAGS, 147 final double defaultValue, 148 final Function<String, Double> optionalParser 149 ) 150 { 151 return PARSE( 152 ja, index, FLAGS, defaultValue, Double.class, optionalParser, 153 RJInternal::DOUBLE_WITH_CHECK, BigDecimal::doubleValue 154 ); 155 } 156 157 /** 158 * <EMBED CLASS='external-html' DATA-TYPE=Integer DATA-FILE-ID=PARSE_BOXED_WF_JA> 159 * @see #PARSE(JsonArray, int, int, Number, Class, Function, Function, Function) 160 */ 161 @IntoHTMLTable( 162 title="Retrieve a JsonString from a JsonArray index, and parse to a Boxed-Float", 163 background=GreenDither 164 ) 165 public static Float parseFloat( 166 final JsonArray ja, 167 final int index, 168 final int FLAGS, 169 final float defaultValue, 170 final Function<String, Float> optionalParser 171 ) 172 { 173 return PARSE( 174 ja, index, FLAGS, defaultValue, Float.class, optionalParser, 175 RJInternal::FLOAT_WITH_CHECK, BigDecimal::floatValue 176 ); 177 } 178 179 180 // ******************************************************************************************** 181 // ******************************************************************************************** 182 // Parse from a JsonObject, into a Boxed-Primitive. ACCEPT USER ERROR-CONTROl FLAGS 183 // ******************************************************************************************** 184 // ******************************************************************************************** 185 186 187 /** 188 * <EMBED CLASS='external-html' DATA-TYPE=Integer DATA-FILE-ID=PARSE_BOXED_WF_JO> 189 * @see #PARSE(JsonObject, String, int, Number, Class, Function, Function, Function) 190 */ 191 @IntoHTMLTable( 192 title="Retrieve a JsonString from a JsonObject property, and parse to a Boxed-Integer", 193 background=BlueDither 194 ) 195 public static Integer parseInteger( 196 final JsonObject jo, 197 final String propertyName, 198 final int FLAGS, 199 final int defaultValue, 200 final Function<String, Integer> optionalParser 201 ) 202 { 203 return PARSE( 204 jo, propertyName, FLAGS, defaultValue, Integer.class, optionalParser, 205 BigDecimal::intValueExact, BigDecimal::intValue 206 ); 207 } 208 209 /** 210 * <EMBED CLASS='external-html' DATA-TYPE=Long DATA-FILE-ID=PARSE_BOXED_WF_JO> 211 * @see #PARSE(JsonObject, String, int, Number, Class, Function, Function, Function) 212 */ 213 @IntoHTMLTable( 214 title= "Retrieve a JsonString from a JsonObject property, and parse to a Boxed Long " + 215 "Integer", 216 background=GreenDither 217 ) 218 public static Long parseLong( 219 final JsonObject jo, 220 final String propertyName, 221 final int FLAGS, 222 final long defaultValue, 223 final Function<String, Long> optionalParser 224 ) 225 { 226 return PARSE( 227 jo, propertyName, FLAGS, defaultValue, Long.class, optionalParser, 228 BigDecimal::longValueExact, BigDecimal::longValue 229 ); 230 } 231 232 /** 233 * <EMBED CLASS='external-html' DATA-TYPE=Short DATA-FILE-ID=PARSE_BOXED_WF_JO> 234 * @see #PARSE(JsonObject, String, int, Number, Class, Function, Function, Function) 235 */ 236 @IntoHTMLTable( 237 title= "Retrieve a JsonString from a JsonObject property, and parse to a Boxed Short " + 238 "Integer", 239 background=BlueDither 240 ) 241 public static Short parseShort( 242 final JsonObject jo, 243 final String propertyName, 244 final int FLAGS, 245 final short defaultValue, 246 final Function<String, Short> optionalParser 247 ) 248 { 249 return PARSE( 250 jo, propertyName, FLAGS, defaultValue, Short.class, optionalParser, 251 BigDecimal::shortValueExact, BigDecimal::shortValue 252 ); 253 } 254 255 /** 256 * <EMBED CLASS='external-html' DATA-TYPE=Byte DATA-FILE-ID=PARSE_BOXED_WF_JO> 257 * @see #PARSE(JsonObject, String, int, Number, Class, Function, Function, Function) 258 */ 259 @IntoHTMLTable( 260 title="Retrieve a JsonString from a JsonObject property, and parse to a Boxed-Byte", 261 background=GreenDither 262 ) 263 public static Byte parseByte( 264 final JsonObject jo, 265 final String propertyName, 266 final int FLAGS, 267 final byte defaultValue, 268 final Function<String, Byte> optionalParser 269 ) 270 { 271 return PARSE( 272 jo, propertyName, FLAGS, defaultValue, Byte.class, optionalParser, 273 BigDecimal::byteValueExact, BigDecimal::byteValue 274 ); 275 } 276 277 /** 278 * <EMBED CLASS='external-html' DATA-TYPE=Double DATA-FILE-ID=PARSE_BOXED_WF_JO> 279 * @see #PARSE(JsonObject, String, int, Number, Class, Function, Function, Function) 280 */ 281 @IntoHTMLTable( 282 title="Retrieve a JsonString from a JsonObject property, and parse to a Boxed-Double", 283 background=BlueDither 284 ) 285 public static Double parseDouble( 286 final JsonObject jo, 287 final String propertyName, 288 final int FLAGS, 289 final double defaultValue, 290 final Function<String, Double> optionalParser 291 ) 292 { 293 return PARSE( 294 jo, propertyName, FLAGS, defaultValue, Double.class, optionalParser, 295 RJInternal::DOUBLE_WITH_CHECK, BigDecimal::doubleValue 296 ); 297 } 298 299 /** 300 * <EMBED CLASS='external-html' DATA-TYPE=Float DATA-FILE-ID=PARSE_BOXED_WF_JO> 301 * @see #PARSE(JsonObject, String, int, Number, Class, Function, Function, Function) 302 */ 303 @IntoHTMLTable( 304 title="Retrieve a JsonString from a JsonObject property, and parse to a Boxed-Float", 305 background=GreenDither 306 ) 307 public static Float parseFloat( 308 final JsonObject jo, 309 final String propertyName, 310 final int FLAGS, 311 final float defaultValue, 312 final Function<String, Float> optionalParser 313 ) 314 { 315 return PARSE( 316 jo, propertyName, FLAGS, defaultValue, Float.class, optionalParser, 317 RJInternal::FLOAT_WITH_CHECK, BigDecimal::floatValue 318 ); 319 } 320 321 322 // ******************************************************************************************** 323 // ******************************************************************************************** 324 // Parse from a JsonArray, into a Boxed-Primitive. NO FLAGS, ALWAYS THROW ON ERROR 325 // ******************************************************************************************** 326 // ******************************************************************************************** 327 328 329 /** 330 * <EMBED CLASS='external-html' DATA-TYPE=Integer DATA-FILE-ID=PARSE_BOXED_NF_JA> 331 * @see #PARSE(JsonObject, String, int, Number, Class, Function, Function, Function) 332 */ 333 @IntoHTMLTable( 334 title="Retrieve a JsonString from a JsonArray index, and parse to a Boxed-Integer", 335 background=BlueDither 336 ) 337 public static Integer parseInteger(final JsonArray ja, final int index) 338 { return PARSE_NO_FLAGS(ja, index, Integer.class, Integer::parseInt); } 339 340 /** 341 * <EMBED CLASS='external-html' DATA-TYPE=Long DATA-FILE-ID=PARSE_BOXED_NF_JA> 342 * @see #PARSE_NO_FLAGS(JsonArray, int, Class, Function) 343 */ 344 @IntoHTMLTable( 345 title="Retrieve a JsonString from a JsonArray index, and parse to a Boxed Long Integer", 346 background=GreenDither 347 ) 348 public static Long parseLong(final JsonArray ja, final int index) 349 { return PARSE_NO_FLAGS(ja, index, Long.class, Long::parseLong); } 350 351 /** 352 * <EMBED CLASS='external-html' DATA-TYPE=Short DATA-FILE-ID=PARSE_BOXED_NF_JA> 353 * @see #PARSE_NO_FLAGS(JsonArray, int, Class, Function) 354 */ 355 @IntoHTMLTable( 356 title="Retrieve a JsonString from a JsonArray index, and parse to a Boxed Short Integer", 357 background=BlueDither 358 ) 359 public static Short parseShort(final JsonArray ja, final int index) 360 { return PARSE_NO_FLAGS(ja, index, Short.class, Short::parseShort); } 361 362 /** 363 * <EMBED CLASS='external-html' DATA-TYPE=Byte DATA-FILE-ID=PARSE_BOXED_NF_JA> 364 * @see #PARSE_NO_FLAGS(JsonArray, int, Class, Function) 365 */ 366 @IntoHTMLTable( 367 title="Retrieve a JsonString from a JsonArray index, and parse to a Boxed-Byte", 368 background=GreenDither 369 ) 370 public static Byte parseByte(final JsonArray ja, final int index) 371 { return PARSE_NO_FLAGS(ja, index, Byte.class, Byte::parseByte); } 372 373 /** 374 * <EMBED CLASS='external-html' DATA-TYPE=Double DATA-FILE-ID=PARSE_BOXED_NF_JA> 375 * @see #PARSE_NO_FLAGS(JsonArray, int, Class, Function) 376 */ 377 @IntoHTMLTable( 378 title="Retrieve a JsonString from a JsonArray index, and parse to a Boxed-Double", 379 background=BlueDither 380 ) 381 public static Double parseDouble(final JsonArray ja, final int index) 382 { return PARSE_NO_FLAGS(ja, index, Double.class, Double::parseDouble); } 383 384 /** 385 * <EMBED CLASS='external-html' DATA-TYPE=Float DATA-FILE-ID=PARSE_BOXED_NF_JA> 386 * @see #PARSE_NO_FLAGS(JsonArray, int, Class, Function) 387 */ 388 @IntoHTMLTable( 389 title="Retrieve a JsonString from a JsonArray index, and parse to a Boxed-Float", 390 background=GreenDither 391 ) 392 public static Float parseFloat(final JsonArray ja, final int index) 393 { return PARSE_NO_FLAGS(ja, index, Float.class, Float::parseFloat); } 394 395 396 // ******************************************************************************************** 397 // ******************************************************************************************** 398 // Parse from a JsonObject, into a Boxed-Primitive. NO FLAGS, ALWAYS THROW ON ERROR 399 // ******************************************************************************************** 400 // ******************************************************************************************** 401 402 403 /** 404 * <EMBED CLASS='external-html' DATA-TYPE=Integer DATA-FILE-ID=PARSE_BOXED_NF_JO> 405 * @see #PARSE_NO_FLAGS(JsonObject, String, boolean, Class, Function) 406 */ 407 @IntoHTMLTable( 408 title="Retrieve a JsonString from a JsonObject property, and parse to a Boxed-Integer", 409 background=BlueDither 410 ) 411 public static Integer parseInteger 412 (final JsonObject jo, final String propertyName, final boolean isOptional) 413 { return PARSE_NO_FLAGS(jo, propertyName, isOptional, Integer.class, Integer::parseInt); } 414 415 /** 416 * <EMBED CLASS='external-html' DATA-TYPE=Long DATA-FILE-ID=PARSE_BOXED_NF_JO> 417 * @see #PARSE_NO_FLAGS(JsonObject, String, boolean, Class, Function) 418 */ 419 @IntoHTMLTable( 420 title= "Retrieve a JsonString from a JsonObject property, and parse to a Boxed Long " + 421 "Integer", 422 background=GreenDither 423 ) 424 public static Long parseLong 425 (final JsonObject jo, final String propertyName, final boolean isOptional) 426 { return PARSE_NO_FLAGS(jo, propertyName, isOptional, Long.class, Long::parseLong); } 427 428 /** 429 * <EMBED CLASS='external-html' DATA-TYPE=Short DATA-FILE-ID=PARSE_BOXED_NF_JO> 430 * @see #PARSE_NO_FLAGS(JsonObject, String, boolean, Class, Function) 431 */ 432 @IntoHTMLTable( 433 title= "Retrieve a JsonString from a JsonObject property, and parse to a Boxed Short " + 434 "Integer", 435 background=BlueDither 436 ) 437 public static Short parseShort 438 (final JsonObject jo, final String propertyName, final boolean isOptional) 439 { return PARSE_NO_FLAGS(jo, propertyName, isOptional, Short.class, Short::parseShort); } 440 441 /** 442 * <EMBED CLASS='external-html' DATA-TYPE=Byte DATA-FILE-ID=PARSE_BOXED_NF_JO> 443 * @see #PARSE_NO_FLAGS(JsonObject, String, boolean, Class, Function) 444 */ 445 @IntoHTMLTable( 446 title="Retrieve a JsonString from a JsonObject property, and parse to a Boxed-Byte", 447 background=GreenDither 448 ) 449 public static Byte parseByte 450 (final JsonObject jo, final String propertyName, final boolean isOptional) 451 { return PARSE_NO_FLAGS(jo, propertyName, isOptional, Byte.class, Byte::parseByte); } 452 453 /** 454 * <EMBED CLASS='external-html' DATA-TYPE=Double DATA-FILE-ID=PARSE_BOXED_NF_JO> 455 * @see #PARSE_NO_FLAGS(JsonObject, String, boolean, Class, Function) 456 */ 457 @IntoHTMLTable( 458 title="Retrieve a JsonString from a JsonObject property, and parse to a Boxed-Double", 459 background=BlueDither 460 ) 461 public static Double parseDouble 462 (final JsonObject jo, final String propertyName, final boolean isOptional) 463 { return PARSE_NO_FLAGS(jo, propertyName, isOptional, Double.class, Double::parseDouble); } 464 465 /** 466 * <EMBED CLASS='external-html' DATA-TYPE=Float DATA-FILE-ID=PARSE_BOXED_NF_JO> 467 * @see #PARSE_NO_FLAGS(JsonObject, String, boolean, Class, Function) 468 */ 469 @IntoHTMLTable( 470 title="Retrieve a JsonString from a JsonObject property, and parse to a Boxed-Float", 471 background=GreenDither 472 ) 473 public static Float parseFloat 474 (final JsonObject jo, final String propertyName, final boolean isOptional) 475 { return PARSE_NO_FLAGS(jo, propertyName, isOptional, Float.class, Float::parseFloat); } 476 477 478 // ******************************************************************************************** 479 // ******************************************************************************************** 480 // Boxed Boolean - ACCEPT USER ERROR-CONTROl FLAGS 481 // ******************************************************************************************** 482 // ******************************************************************************************** 483 484 485 /** <EMBED CLASS='external-html' DATA-TYPE=Boolean DATA-FILE-ID=PARSE_BOXED_WF_JA> */ 486 @IntoHTMLTable( 487 title="Retrieve a JsonString from a JsonArray index, and parse to a Boxed-Boolean", 488 background=BlueDither 489 ) 490 public static Boolean parseBoolean( 491 final JsonArray ja, 492 final int index, 493 final int FLAGS, 494 final boolean defaultValue, 495 final Function<String, Boolean> optionalParser 496 ) 497 { 498 if (index >= ja.size()) return IOOBEX(ja, index, defaultValue, FLAGS); 499 500 final JsonValue jv = ja.get(index); 501 502 switch (jv.getValueType()) 503 { 504 case NULL: return JNAEX(ja, index, defaultValue, FLAGS, STRING, Boolean.class); 505 506 case STRING: 507 508 final String s = ((JsonString) jv).getString(); 509 510 if (s.length() == 0) 511 { 512 if ((FLAGS & RETURN_NULL_ON_0LEN_STR) != 0) return null; 513 if ((FLAGS & RETURN_DEFVAL_ON_0LEN_STR) != 0) return defaultValue; 514 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 515 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 516 } 517 518 try 519 { 520 return (optionalParser != null) 521 ? optionalParser.apply(s) 522 : Boolean.parseBoolean(s.trim()); 523 } 524 525 catch (Exception e) 526 { return JSPAEX(e, ja, index, defaultValue, FLAGS, jv, Boolean.class); } 527 528 default: return JTAEX(ja, index, defaultValue, FLAGS, STRING, jv, Boolean.class); 529 } 530 } 531 532 /** <EMBED CLASS='external-html' DATA-TYPE=Boolean DATA-FILE-ID=PARSE_BOXED_WF_JO> */ 533 @IntoHTMLTable( 534 title="Retrieve a JsonString from a JsonObject property, and parse to a Boxed-Integer", 535 background=GreenDither 536 ) 537 public static Boolean parseBoolean( 538 final JsonObject jo, 539 final String propertyName, 540 final int FLAGS, 541 final boolean defaultValue, 542 final Function<String, Boolean> optionalParser 543 ) 544 { 545 546 final JsonValue jv = jo.get(propertyName); 547 548 if (jv == null) return JPMEX(jo, propertyName, defaultValue, FLAGS, STRING, Boolean.class); 549 550 switch (jv.getValueType()) 551 { 552 case NULL: return JNOEX(jo, propertyName, defaultValue, FLAGS, STRING, Boolean.class); 553 554 case STRING: 555 556 final String s = ((JsonString) jv).getString(); 557 558 if (s.length() == 0) 559 { 560 if ((FLAGS & RETURN_NULL_ON_0LEN_STR) != 0) return null; 561 if ((FLAGS & RETURN_DEFVAL_ON_0LEN_STR) != 0) return defaultValue; 562 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 563 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 564 } 565 566 try 567 { 568 return (optionalParser != null) 569 ? optionalParser.apply(s) 570 : Boolean.parseBoolean(s.trim()); 571 } 572 573 catch (Exception e) 574 { return JSPOEX(e, jo, propertyName, defaultValue, FLAGS, jv, Boolean.class); } 575 576 default: return JTOEX(jo, propertyName, defaultValue, FLAGS, STRING, jv, Boolean.class); 577 } 578 } 579 580 581 // ******************************************************************************************** 582 // ******************************************************************************************** 583 // Boolean - NO FLAGS, ALWAYS THROW ON ERROR 584 // ******************************************************************************************** 585 // ******************************************************************************************** 586 587 588 /** <EMBED CLASS='external-html' DATA-TYPE=Boolean DATA-FILE-ID=PARSE_BOXED_NF_JA> */ 589 @IntoHTMLTable( 590 title="Retrieve a JsonString from a JsonArray index, and parse to a Boxed-Boolean", 591 background=BlueDither 592 ) 593 public static Boolean parseBoolean(final JsonArray ja, final int i) 594 { 595 // Throws an IndexOutOfBoundsException 596 final JsonValue jv = ja.get(i); 597 598 switch (jv.getValueType()) 599 { 600 case NULL: return null; 601 602 case STRING: 603 604 try 605 { return Boolean.parseBoolean(((JsonString) jv).getString()); } 606 607 catch (Exception e) 608 { throw new JsonStrParseArrException (e, ja, i, jv, Boolean.class); } 609 610 default: throw new JsonTypeArrException(ja, i, STRING, jv, Boolean.class); 611 } 612 } 613 614 /** <EMBED CLASS='external-html' DATA-TYPE=Boolean DATA-FILE-ID=PARSE_BOXED_NF_JO> */ 615 @IntoHTMLTable( 616 title="Retrieve a JsonString from a JsonObject property, and parse to a Boxed-Integer", 617 background=GreenDither 618 ) 619 public static Boolean parseBoolean 620 (final JsonObject jo, final String propertyName, final boolean isOptional) 621 { 622 final JsonValue jv = jo.get(propertyName); 623 624 if (jv == null) 625 { 626 if (isOptional) return null; 627 else throw new JsonPropMissingException(jo, propertyName, STRING, Boolean.class); 628 } 629 630 switch (jv.getValueType()) 631 { 632 case NULL: return null; 633 634 case STRING: 635 636 try 637 { return Boolean.parseBoolean(((JsonString) jv).getString()); } 638 639 catch (Exception e) 640 { throw new JsonStrParseObjException(e, jo, propertyName, jv, Boolean.class); } 641 642 default: throw new JsonTypeObjException(jo, propertyName, STRING, jv, Boolean.class); 643 } 644 } 645 646 647 // ******************************************************************************************** 648 // ******************************************************************************************** 649 // HELPER PARSE - JsonString Inputs (USES FLAGS) 650 // ******************************************************************************************** 651 // ******************************************************************************************** 652 653 654 /** 655 * Retrieve a {@link JsonArray} element containing a {@link JsonString}, and transform it to 656 * a <B STYLE='color: red'>Java Type</B>, with either a user-provided parser, or the standard 657 * java parser for that class (passed as a parameter). 658 * 659 * @param <T> The type of the returned value 660 * @param ja Any instance of {@link JsonArray} 661 * @param index array-index containing the {@link JsonString} to retrieve. 662 * @param FLAGS The return-value / exception-throw flag constants defined in {@link JFlag} 663 * @param defaultValue User-provided default-value, only returned if flags are set. 664 * @param optionalParser A valid {@code String -> 'T'} parser. This parameter may be null. 665 * @param defaultParser1 Default {@code String -> 'T'} parser. 666 * @param defaultParser2 {@code String -> 'T'} parser, that will round on Arithmetic Exceptions 667 * 668 * @return On success, this method returns the converted type. 669 * 670 * @throws JsonPropMissingException {@code 'jo'} doesn't have {@code 'propertyName'}, unless 671 * flags are set. 672 * @throws JsonArithmeticArrException after parse, conversion fails, and flags aren't set 673 * @throws JsonStrParseArrException parser-failure unless flags are set 674 * @throws JsonNullArrException property contains null, unless flags are set 675 * @throws JsonTypeArrException property doesn't contain {@code JsonString}, unless flags are 676 * set. 677 * 678 * @see #parseInteger(JsonArray, int, int, int, Function) 679 * @see #parseLong(JsonArray, int, int, long, Function) 680 * @see #parseShort(JsonArray, int, int, short, Function) 681 * @see #parseByte(JsonArray, int, int, byte, Function) 682 * @see #parseDouble(JsonArray, int, int, double, Function) 683 * @see #parseFloat(JsonArray, int, int, float, Function) 684 * 685 * @see ReadNumberJSON#parse(JsonArray, int, int, Number, Function) 686 * 687 * @see RJInternal#IOOBEX(JsonArray, int, Object, int) 688 * @see RJInternal#JNAEX(JsonArray, int, Object, int, JsonValue.ValueType, Class) 689 * @see RJInternal#JSPAEX(Exception, JsonArray, int, Object, int, JsonValue, Class) 690 * @see RJInternal#JTAEX(JsonArray, int, Object, int, JsonValue.ValueType, JsonValue, Class) 691 */ 692 protected static <T extends Number> T PARSE( 693 final JsonArray ja, 694 final int index, 695 final int FLAGS, 696 final T defaultValue, 697 final Class<T> returnClass, 698 final Function<String, T> optionalParser, 699 final Function<BigDecimal, T> defaultParser1, 700 final Function<BigDecimal, T> defaultParser2 701 ) 702 { 703 // When TRUE, the index provided turned out to be outside of the bounds of the array. The 704 // IndexOutOfBounds "handler" (the method called here) will check the FLAGS, and: 705 // 706 // 1) return the defaultValue (if Requested by 'FLAGS' for IOOBEX) 707 // 2) return null (if Requested by 'FLAGS' for IOOBEX) 708 // 3) throw IndexOutOfBoundsException 709 // 710 // NOTE: It is probably a "little less efficient" to turn this into a method call, 711 // since there are all these parameters that have to be passed, but this is 712 // trading "readability" (less head-aches) in exchange for efficiency. 713 // 714 // This point applies to all of the "Exception Flag Handlers" used here 715 716 if (index >= ja.size()) return IOOBEX(ja, index, defaultValue, FLAGS); 717 718 final JsonValue jv = ja.get(index); 719 720 switch (jv.getValueType()) 721 { 722 // When a 'NULL' (Json-Null) JsonValue is present, the JsonNullArrException 'handler' 723 // will do one of the following: 724 // 725 // 1) return the defaultValue (if Requested by 'FLAGS' for JNAEX) 726 // 2) return null (if Requested by 'FLAGS' for JNAEX) 727 // 3) throw JsonNullArrException 728 729 case NULL: return JNAEX(ja, index, defaultValue, FLAGS, STRING, returnClass); 730 731 case STRING: 732 733 final String s = ((JsonString) jv).getString(); 734 735 // NOTE: This isn't actually an "Exception Case", and if the user hasn't made 736 // a request, the empty-string is passed to whatever parser is configured 737 738 if (s.length() == 0) 739 { 740 if ((FLAGS & RETURN_NULL_ON_0LEN_STR) != 0) return null; 741 if ((FLAGS & RETURN_DEFVAL_ON_0LEN_STR) != 0) return defaultValue; 742 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 743 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 744 } 745 746 // Temp Variable, used in order not to invoke the BigDecimal contructor twice 747 BigDecimal bd = null; 748 749 try 750 { 751 // NOTE: 'bd' will not be null if "ArithmeticException" is thrown... 752 // new BigDecimal throws "NumberFormatException" is thrown 753 // optionalParser.apply can throw ArithmeticException 754 755 return (optionalParser != null) 756 ? optionalParser.apply(s) 757 : defaultParser1.apply(bd = new BigDecimal(s.trim())); 758 } 759 760 761 // Because 762 // 763 // 1) A method for this code would only be invoked here, and... 764 // 2) And because there would be 9 parameters to pass, 765 // 3) the 'inline' version of "Flag Handler" is left here! 766 // 767 // NOTE: All four "JsonArithmetic Arr/Obj Exception" exception throws 768 // are different for each of the 4 methods where they are used. 769 770 catch (ArithmeticException ae) 771 { 772 if ((FLAGS & RETURN_NULL_ON_AEX) != 0) return null; 773 if ((FLAGS & RETURN_DEFVAL_ON_AEX) != 0) return defaultValue; 774 if ((FLAGS & RETURN_JAPPROX_ON_AEX) != 0) return defaultParser2.apply(bd); 775 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 776 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 777 778 throw new JsonArithmeticArrException(ae, ja, index, STRING, jv, returnClass); 779 } 780 781 782 // HANDLER STRIKES AGAIN! - but this time for "JsonStrParseArrException" 783 // RETURNS: null, or defaultValue, (otherwise throws JsonStrParseArrException) 784 785 catch (Exception e) 786 { return JSPAEX(e, ja, index, defaultValue, FLAGS, jv, returnClass); } 787 788 789 // The JsonValue at the specified array-index does not contain an JsonString. 790 // The "JsonTypeArrException Handler" will do one of these: 791 // 792 // 1) return the defaultValue (if Requested by 'FLAGS' for JTAEX) 793 // 2) return null (if Requested by 'FLAGS' for JTAEX) 794 // 3) throw JsonTypeArrException 795 796 default: return JTAEX(ja, index, defaultValue, FLAGS, STRING, jv, returnClass); 797 } 798 } 799 800 /** 801 * Retrieve a {@link JsonObject} property containing a {@link JsonString}, and transform it to 802 * a <B STYLE='color: red'>Java Type</B>, with either a user-provided parser, or the standard 803 * java parser for that class (passed as a parameter). 804 * 805 * @param <T> The type of the returned value. 806 * @param jo Any instance of {@link JsonObject} 807 * @param propertyName propertyName containing the {@link JsonString} to retrieve. 808 * @param FLAGS The return-value / exception-throw flag constants defined in {@link JFlag} 809 * @param defaultValue User-provided default-value, only returned if flags are set. 810 * @param optionalParser A valid {@code String -> 'T'} parser. This parameter may be null. 811 * @param defaultParser1 Default {@code String -> 'T'} parser. 812 * @param defaultParser2 {@code String -> 'T'} parser, that will round on Arithmetic Exceptions 813 * 814 * @return On success, this method returns the converted type instance. 815 * 816 * @throws JsonPropMissingException {@code 'jo'} doesn't have {@code 'propertyName'}, unless 817 * flags are set. 818 * @throws JsonArithmeticObjException after parse, conversion fails, and flags aren't set 819 * @throws JsonStrParseObjException parser-failure unless flags are set 820 * @throws JsonNullObjException property contains null, unless flags are set 821 * @throws JsonTypeObjException property doesn't contain {@code JsonString}, unless flags are 822 * set. 823 * 824 * @see #parseInteger(JsonObject, String, int, int, Function) 825 * @see #parseLong(JsonObject, String, int, long, Function) 826 * @see #parseShort(JsonObject, String, int, short, Function) 827 * @see #parseByte(JsonObject, String, int, byte, Function) 828 * @see #parseDouble(JsonObject, String, int, double, Function) 829 * @see #parseFloat(JsonObject, String, int, float, Function) 830 * 831 * @see ReadNumberJSON#parse(JsonObject, String, int, Number, Function) 832 * 833 * @see RJInternal#JPMEX(JsonObject, String, Object, int, JsonValue.ValueType, Class) 834 * @see RJInternal#JNOEX(JsonObject, String, Object, int, JsonValue.ValueType, Class) 835 * @see RJInternal#JSPOEX(Exception, JsonObject, String, Object, int, JsonValue, Class) 836 * @see RJInternal#JTOEX(JsonObject, String, Object, int, JsonValue.ValueType, JsonValue, Class) 837 */ 838 protected static <T extends Number> T PARSE( 839 final JsonObject jo, 840 final String propertyName, 841 final int FLAGS, 842 final T defaultValue, 843 final Class<T> returnClass, 844 final Function<String, T> optionalParser, 845 final Function<BigDecimal, T> defaultParser1, 846 final Function<BigDecimal, T> defaultParser2 847 ) 848 { 849 final JsonValue jv = jo.get(propertyName); 850 851 852 // When TRUE, the user-specified 'property' (named by 'propertyName') isn't actually one 853 // of the listed properties inside the JsonObject. The JsonPropMissingException "handler" 854 // (the method called here) will check the FLAGS, and: 855 // 856 // 1) return the defaultValue (if Requested by 'FLAGS' for JPMEX) 857 // 2) return null (if Requested by 'FLAGS' for JPMEX) 858 // 3) throw JsonPropMissingException 859 // 860 // NOTE: It is probably a "little less efficient" to turn this into a method call, 861 // since there are all these parameters that have to be passed, but this is 862 // trading "readability" (less head-aches) in exchange for efficiency. 863 // 864 // This point applies to all of the "Exception Flag Handlers" used here 865 866 if (jv == null) return JPMEX(jo, propertyName, defaultValue, FLAGS, STRING, returnClass); 867 868 switch (jv.getValueType()) 869 { 870 // When a 'NULL' (Json-Null) JsonValue is present, the JsonNullObjException 'handler' 871 // will do one of the following: 872 // 873 // 1) return the defaultValue (if Requested by 'FLAGS' for JNOEX) 874 // 2) return null (if Requested by 'FLAGS' for JNOEX) 875 // 3) throw JsonNullArrException 876 877 case NULL: return JNOEX(jo, propertyName, defaultValue, FLAGS, STRING, returnClass); 878 879 case STRING: 880 881 final String s = ((JsonString) jv).getString(); 882 883 884 // NOTE: This isn't actually an "Exception Case", and if the user hasn't made 885 // a request, the empty-string is passed to whatever parser is configured 886 887 if (s.length() == 0) 888 { 889 if ((FLAGS & RETURN_NULL_ON_0LEN_STR) != 0) return null; 890 if ((FLAGS & RETURN_DEFVAL_ON_0LEN_STR) != 0) return defaultValue; 891 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 892 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 893 } 894 895 // Temp Variable, used in order not to invoke the BigDecimal contructor twice 896 BigDecimal bd = null; 897 898 try 899 { 900 // NOTE: 'bd' will not be null if "ArithmeticException" is thrown... 901 // new BigDecimal throws "NumberFormatException" is thrown 902 // parsoptionalParserer.apply can throw ArithmeticException 903 904 return (optionalParser != null) 905 ? optionalParser.apply(s) 906 : defaultParser1.apply(bd = new BigDecimal(s.trim())); 907 } 908 909 910 // Because 911 // 912 // 1) A method for this code would only be invoked here, and... 913 // 2) And because there would be 9 parameters to pass, 914 // 3) the 'inline' version of "Flag Handler" is left here! 915 // 916 // NOTE: All four "JsonArithmetic Arr/Obj Exception" exception throws 917 // are different for each of the 4 methods where they are used. 918 919 catch (ArithmeticException ae) 920 { 921 if ((FLAGS & RETURN_NULL_ON_AEX) != 0) return null; 922 if ((FLAGS & RETURN_DEFVAL_ON_AEX) != 0) return defaultValue; 923 if ((FLAGS & RETURN_JAPPROX_ON_AEX) != 0) return defaultParser2.apply(bd); 924 if ((FLAGS & RETURN_NULL_ON_ANY_ALL) != 0) return null; 925 if ((FLAGS & RETURN_DEFVAL_ON_ANY_ALL) != 0) return defaultValue; 926 927 throw new JsonArithmeticObjException 928 (ae, jo, propertyName, STRING, jv, returnClass); 929 } 930 931 932 // HANDLER STRIKES AGAIN! - but this time for "JsonStrParseObjException" 933 // RETURNS: null, or defaultValue, (otherwise throws JsonStrParseObjException) 934 935 catch (Exception e) 936 { return JSPOEX(e, jo, propertyName, defaultValue, FLAGS, jv, returnClass); } 937 938 939 // The JsonValue of 'propertyName' does not contain an JsonString. 940 // The "JsonTypeObjException Handler" will do one of these: 941 // 942 // 1) return the defaultValue (if Requested by 'FLAGS' for JTOEX) 943 // 2) return null (if Requested by 'FLAGS' for JTOEX) 944 // 3) throw JsonTypeObjException 945 946 default: return JTOEX(jo, propertyName, defaultValue, FLAGS, STRING, jv, returnClass); 947 } 948 } 949 950 951 // ******************************************************************************************** 952 // ******************************************************************************************** 953 // HELPER PARSE #2 - JsonString Inputs (WITHOUT FLAGS) 954 // ******************************************************************************************** 955 // ******************************************************************************************** 956 957 958 /** 959 * This is an internal helper method for retrieving an element from a {@link JsonArray}, 960 * and converting it to one of the standard <B STYLE='color: red;'>Java Types</B>. 961 * 962 * @param <T> Numeric Boxed-Type, as an instance of {@code java.lang.Class} 963 * @param ja Any instance of {@link JsonArray} 964 * @param index A valid index into {@code 'ja'} 965 * @param returnClass Internally specified Numeric Boxed-Type, used for Type Inference 966 * @param parser <EMBED CLASS='external-html' DATA-FILE-ID=COMMON_PARSER> 967 * 968 * @return The converted number, as an instance of Generic-Parameter {@code 'T'} 969 * 970 * @see #parseInteger(JsonArray, int) 971 * @see #parseLong(JsonArray, int) 972 * @see #parseShort(JsonArray, int) 973 * @see #parseByte(JsonArray, int) 974 * @see #parseDouble(JsonArray, int) 975 * @see #parseFloat(JsonArray, int) 976 */ 977 protected static <T extends Number> T PARSE_NO_FLAGS( 978 final JsonArray ja, 979 final int index, 980 final Class<T> returnClass, 981 final Function<String, T> parser 982 ) 983 { 984 // Throws an IndexOutOfBoundsException 985 final JsonValue jv = ja.get(index); 986 987 switch (jv.getValueType()) 988 { 989 case NULL: return null; 990 991 case STRING: 992 993 try 994 { return parser.apply(((JsonString) jv).getString()); } 995 996 catch (ArithmeticException ae) 997 { throw new JsonArithmeticArrException(ae, ja, index, STRING, jv, returnClass);} 998 999 catch (Exception e) 1000 { throw new JsonStrParseArrException (e, ja, index, jv, returnClass); } 1001 1002 default: throw new JsonTypeArrException(ja, index, STRING, jv, returnClass); 1003 } 1004 } 1005 1006 1007 /** 1008 * This is an internal helper method for retrieving a property from a {@link JsonObject}, 1009 * and converting it to one of the standard <B STYLE='color: red;'>Java Types</B>. 1010 * 1011 * @param <T> Numeric Boxed-Type, as an instance of {@code java.lang.Class} 1012 * @param jo Any instance of {@link JsonObject} 1013 * @param propertyName Any property name contained by {@code 'jo'} 1014 * @param isOptional <EMBED CLASS='external-html' DATA-FILE-ID=COMMON_IS_OPTIONAL> 1015 * @param parser <EMBED CLASS='external-html' DATA-FILE-ID=COMMON_PARSER> 1016 * 1017 * @return The converted number, as an instance of Generic-Parameter {@code 'T'} 1018 * 1019 * @see #parseInteger(JsonObject, String, boolean) 1020 * @see #parseLong(JsonObject, String, boolean) 1021 * @see #parseShort(JsonObject, String, boolean) 1022 * @see #parseByte(JsonObject, String, boolean) 1023 * @see #parseDouble(JsonObject, String, boolean) 1024 * @see #parseFloat(JsonObject, String, boolean) 1025 */ 1026 protected static <T extends Number> T PARSE_NO_FLAGS( 1027 final JsonObject jo, 1028 final String propertyName, 1029 final boolean isOptional, 1030 final Class<T> returnClass, 1031 final Function<String, T> parser 1032 ) 1033 { 1034 final JsonValue jv = jo.get(propertyName); 1035 1036 if (jv == null) 1037 { 1038 if (isOptional) 1039 return null; 1040 else 1041 throw new JsonPropMissingException(jo, propertyName, STRING, returnClass); 1042 } 1043 1044 switch (jv.getValueType()) 1045 { 1046 case NULL: return null; 1047 1048 case STRING: 1049 1050 try 1051 { return parser.apply(((JsonString) jv).getString()); } 1052 1053 catch (ArithmeticException ae) 1054 { 1055 throw new JsonArithmeticObjException 1056 (ae, jo, propertyName, STRING, jv, returnClass); 1057 } 1058 1059 catch (Exception e) 1060 { throw new JsonStrParseObjException(e, jo, propertyName, jv, returnClass); } 1061 1062 default: throw new JsonTypeObjException(jo, propertyName, STRING, jv, returnClass); 1063 } 1064 } 1065 1066}