001/* Copyright 2016-2017 Clifton Labs 002 * Licensed under the Apache License, Version 2.0 (the "License"); 003 * you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at 005 * http://www.apache.org/licenses/LICENSE-2.0 006 * Unless required by applicable law or agreed to in writing, software 007 * distributed under the License is distributed on an "AS IS" BASIS, 008 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 009 * See the License for the specific language governing permissions and 010 * limitations under the License. */ 011package org.json.simple; 012 013import java.io.IOException; 014import java.io.StringWriter; 015import java.io.Writer; 016import java.math.BigDecimal; 017import java.util.Collection; 018import java.util.HashMap; 019import java.util.HashSet; 020import java.util.Iterator; 021import java.util.Map; 022import java.util.NoSuchElementException; 023import java.util.Set; 024 025/** JsonObject is a common non-thread safe data format for string to data mappings. The contents of a JsonObject are 026 * only validated as JSON values on serialization. Meaning all values added to a JsonObject must be recognized by the 027 * Jsoner for it to be a true 'JsonObject', so it is really a JsonableHashMap that will serialize to a JsonObject if all of 028 * its contents are valid JSON. 029 * @see Jsoner 030 * @since 2.0.0 */ 031public class JsonObject extends HashMap<String, Object> implements Jsonable{ 032 /** The serialization version this class is compatible 033 * with. This value doesn't need to be incremented if and only if the only changes to occur were updating comments, 034 * updating javadocs, adding new 035 * fields to the class, changing the fields from static to non-static, or changing the fields from transient to non 036 * transient. All other changes require this number be incremented. */ 037 private static final long serialVersionUID = 2L; 038 039 /** Instantiates an empty JsonObject. */ 040 public JsonObject(){ 041 super(); 042 } 043 044 /** Instantiate a new JsonObject by accepting a map's entries, which could lead to de/serialization issues of the 045 * resulting JsonObject since the entry values aren't validated as JSON values. 046 * @param map represents the mappings to produce the JsonObject with. */ 047 public JsonObject(final Map<String, ?> map){ 048 super(map); 049 } 050 051 /** Ensures the given keys are present. 052 * @param keys represents the keys that must be present. 053 * @throws NoSuchElementException if any of the given keys are missing. 054 * @since 2.3.0 to ensure critical keys are in the JsonObject. */ 055 public void requireKeys(final JsonKey... keys){ 056 /* Track all of the missing keys. */ 057 final Set<JsonKey> missing = new HashSet<>(); 058 for(final JsonKey k : keys){ 059 if(!this.containsKey(k.getKey())){ 060 missing.add(k); 061 } 062 } 063 if(!missing.isEmpty()){ 064 /* Report any missing keys in the exception. */ 065 final StringBuilder sb = new StringBuilder(); 066 for(final JsonKey k : missing){ 067 sb.append(k.getKey()).append(", "); 068 } 069 sb.setLength(sb.length() - 2); 070 final String s = missing.size() > 1 ? "s" : ""; 071 throw new NoSuchElementException("A JsonObject is missing required key" + s + ": " + sb.toString()); 072 } 073 } 074 075 /** A convenience method that assumes there is a BigDecimal, Number, or String at the given key. If a Number is 076 * there its Number#toString() is used to construct a new BigDecimal(String). If a String is there it is used to 077 * construct a new BigDecimal(String). 078 * @param key representing where the value ought to be paired with. 079 * @return a BigDecimal representing the value paired with the key. 080 * @throws ClassCastException if the value didn't match the assumed return type. 081 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 082 * represents the double or float Infinity or NaN. 083 * @see BigDecimal 084 * @see Number#toString() 085 * @see JsonKey 086 * @since 2.3.0 to utilize JsonKey */ 087 public BigDecimal getBigDecimal(final JsonKey key){ 088 Object returnable = this.get(key.getKey()); 089 if(returnable instanceof BigDecimal){ 090 /* Success there was a BigDecimal or it defaulted. */ 091 }else if(returnable instanceof Number){ 092 /* A number can be used to construct a BigDecimal */ 093 returnable = new BigDecimal(returnable.toString()); 094 }else if(returnable instanceof String){ 095 /* A number can be used to construct a BigDecimal */ 096 returnable = new BigDecimal((String)returnable); 097 } 098 return (BigDecimal)returnable; 099 } 100 101 /** A convenience method that assumes there is a BigDecimal, Number, or String at the given key. If a Number is 102 * there its Number#toString() is used to construct a new BigDecimal(String). If a String is there it is used to 103 * construct a new BigDecimal(String). 104 * @param key representing where the value ought to be stored at. 105 * @return the value stored at the key. 106 * @throws ClassCastException if the value didn't match the assumed return type. 107 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 108 * represents the double or float Infinity or NaN. 109 * @see BigDecimal 110 * @see Number#toString() 111 * @deprecated 2.3.0 in favor of {@link #getBigDecimal(JsonKey)} */ 112 @Deprecated 113 public BigDecimal getBigDecimal(final String key){ 114 Object returnable = this.get(key); 115 if(returnable instanceof BigDecimal){ 116 /* Success there was a BigDecimal or it defaulted. */ 117 }else if(returnable instanceof Number){ 118 /* A number can be used to construct a BigDecimal */ 119 returnable = new BigDecimal(returnable.toString()); 120 }else if(returnable instanceof String){ 121 /* A number can be used to construct a BigDecimal */ 122 returnable = new BigDecimal((String)returnable); 123 } 124 return (BigDecimal)returnable; 125 } 126 127 /** A convenience method that assumes there is a BigDecimal, Number, or String at the given key. If a Number is 128 * there its Number#toString() is used to construct a new BigDecimal(String). If a String is there it is used to 129 * construct a new BigDecimal(String). 130 * @param key representing where the value ought to be paired with. 131 * @return a BigDecimal representing the value paired with the key or JsonKey#getValue() if the key isn't present. 132 * @throws ClassCastException if the value didn't match the assumed return type. 133 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 134 * represents the double or float Infinity or NaN. 135 * @see BigDecimal 136 * @see Number#toString() 137 * @see JsonKey 138 * @since 2.3.0 to utilize JsonKey */ 139 public BigDecimal getBigDecimalOrDefault(final JsonKey key){ 140 Object returnable; 141 if(this.containsKey(key.getKey())){ 142 returnable = this.get(key.getKey()); 143 }else{ 144 returnable = key.getValue(); 145 } 146 if(returnable instanceof BigDecimal){ 147 /* Success there was a BigDecimal or it defaulted. */ 148 }else if(returnable instanceof Number){ 149 /* A number can be used to construct a BigDecimal */ 150 returnable = new BigDecimal(returnable.toString()); 151 }else if(returnable instanceof String){ 152 /* A String can be used to construct a BigDecimal */ 153 returnable = new BigDecimal((String)returnable); 154 } 155 return (BigDecimal)returnable; 156 } 157 158 /** A convenience method that assumes there is a BigDecimal, Number, or String at the given key. If a Number is 159 * there its Number#toString() is used to construct a new BigDecimal(String). If a String is there it is used to 160 * construct a new BigDecimal(String). 161 * @param key representing where the value ought to be stored at. 162 * @param defaultValue representing what is returned when the key isn't in the JsonObject. 163 * @return the value stored at the key or the default provided if the key doesn't exist. 164 * @throws ClassCastException if there was a value but didn't match the assumed return types. 165 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 166 * represents the double or float Infinity or NaN. 167 * @see BigDecimal 168 * @see Number#toString() 169 * @deprecated 2.3.0 in favor of {@link #getBigDecimalOrDefault(JsonKey)} */ 170 @Deprecated 171 public BigDecimal getBigDecimalOrDefault(final String key, final BigDecimal defaultValue){ 172 Object returnable; 173 if(this.containsKey(key)){ 174 returnable = this.get(key); 175 }else{ 176 return defaultValue; 177 } 178 if(returnable instanceof BigDecimal){ 179 /* Success there was a BigDecimal or it defaulted. */ 180 }else if(returnable instanceof Number){ 181 /* A number can be used to construct a BigDecimal */ 182 returnable = new BigDecimal(returnable.toString()); 183 }else if(returnable instanceof String){ 184 /* A String can be used to construct a BigDecimal */ 185 returnable = new BigDecimal((String)returnable); 186 } 187 return (BigDecimal)returnable; 188 } 189 190 /** A convenience method that assumes there is a Boolean or String value at the given key. 191 * @param key representing where the value ought to be paired with. 192 * @return a Boolean representing the value paired with the key. 193 * @throws ClassCastException if the value didn't match the assumed return type. 194 * @see JsonKey 195 * @since 2.3.0 to utilize JsonKey */ 196 public Boolean getBoolean(final JsonKey key){ 197 Object returnable = this.get(key.getKey()); 198 if(returnable instanceof String){ 199 returnable = Boolean.valueOf((String)returnable); 200 } 201 return (Boolean)returnable; 202 } 203 204 /** A convenience method that assumes there is a Boolean or String value at the given key. 205 * @param key representing where the value ought to be stored at. 206 * @return the value stored at the key. 207 * @throws ClassCastException if the value didn't match the assumed return type. 208 * @deprecated 2.3.0 in favor of {@link #getBoolean(JsonKey)} */ 209 @Deprecated 210 public Boolean getBoolean(final String key){ 211 Object returnable = this.get(key); 212 if(returnable instanceof String){ 213 returnable = Boolean.valueOf((String)returnable); 214 } 215 return (Boolean)returnable; 216 } 217 218 /** A convenience method that assumes there is a Boolean or String value at the given key. 219 * @param key representing where the value ought to be paired with. 220 * @return a Boolean representing the value paired with the key or JsonKey#getValue() if the key isn't present. 221 * @throws ClassCastException if the value didn't match the assumed return type. 222 * @see JsonKey 223 * @since 2.3.0 to utilize JsonKey */ 224 public Boolean getBooleanOrDefault(final JsonKey key){ 225 Object returnable; 226 if(this.containsKey(key.getKey())){ 227 returnable = this.get(key.getKey()); 228 }else{ 229 returnable = key.getValue(); 230 } 231 if(returnable instanceof String){ 232 returnable = Boolean.valueOf((String)returnable); 233 } 234 return (Boolean)returnable; 235 } 236 237 /** A convenience method that assumes there is a Boolean or String value at the given key. 238 * @param key representing where the value ought to be stored at. 239 * @param defaultValue representing what is returned when the key isn't in the JsonObject. 240 * @return the value stored at the key or the default provided if the key doesn't exist. 241 * @throws ClassCastException if there was a value but didn't match the assumed return type. 242 * @deprecated 2.3.0 in favor of {@link #getBooleanOrDefault(JsonKey)} */ 243 @Deprecated 244 public Boolean getBooleanOrDefault(final String key, final boolean defaultValue){ 245 Object returnable; 246 if(this.containsKey(key)){ 247 returnable = this.get(key); 248 }else{ 249 return defaultValue; 250 } 251 if(returnable instanceof String){ 252 returnable = Boolean.valueOf((String)returnable); 253 } 254 return (Boolean)returnable; 255 } 256 257 /** A convenience method that assumes there is a Number or String value at the given key. 258 * @param key representing where the value ought to be paired with. 259 * @return a Byte representing the value paired with the key (which may involve rounding or truncation). 260 * @throws ClassCastException if the value didn't match the assumed return type. 261 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 262 * represents the double or float Infinity or NaN. 263 * @see Number#byteValue() 264 * @see JsonKey 265 * @since 2.3.0 to utilize JsonKey */ 266 public Byte getByte(final JsonKey key){ 267 Object returnable = this.get(key.getKey()); 268 if(returnable == null){ 269 return null; 270 } 271 if(returnable instanceof String){ 272 /* A String can be used to construct a BigDecimal. */ 273 returnable = new BigDecimal((String)returnable); 274 } 275 return ((Number)returnable).byteValue(); 276 } 277 278 /** A convenience method that assumes there is a Number or String value at the given key. 279 * @param key representing where the value ought to be stored at. 280 * @return the value stored at the key (which may involve rounding or truncation). 281 * @throws ClassCastException if the value didn't match the assumed return type. 282 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 283 * represents the double or float Infinity or NaN. 284 * @see Number#byteValue() 285 * @deprecated 2.3.0 in favor of {@link #getByte(JsonKey)} */ 286 @Deprecated 287 public Byte getByte(final String key){ 288 Object returnable = this.get(key); 289 if(returnable == null){ 290 return null; 291 } 292 if(returnable instanceof String){ 293 /* A String can be used to construct a BigDecimal. */ 294 returnable = new BigDecimal((String)returnable); 295 } 296 return ((Number)returnable).byteValue(); 297 } 298 299 /** A convenience method that assumes there is a Number or String value at the given key. 300 * @param key representing where the value ought to be paired with. 301 * @return a Byte representing the value paired with the key or JsonKey#getValue() if the key isn't present (which 302 * may involve rounding or truncation). 303 * @throws ClassCastException if the value didn't match the assumed return type. 304 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 305 * represents the double or float Infinity or NaN. 306 * @see Number#byteValue() 307 * @see JsonKey 308 * @since 2.3.0 to utilize JsonKey */ 309 public Byte getByteOrDefault(final JsonKey key){ 310 Object returnable; 311 if(this.containsKey(key.getKey())){ 312 returnable = this.get(key.getKey()); 313 }else{ 314 returnable = key.getValue(); 315 } 316 if(returnable == null){ 317 return null; 318 } 319 if(returnable instanceof String){ 320 /* A String can be used to construct a BigDecimal. */ 321 returnable = new BigDecimal((String)returnable); 322 } 323 return ((Number)returnable).byteValue(); 324 } 325 326 /** A convenience method that assumes there is a Number or String value at the given key. 327 * @param key representing where the value ought to be stored at. 328 * @param defaultValue representing what is returned when the key isn't in the JsonObject. 329 * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key 330 * doesn't exist. 331 * @throws ClassCastException if there was a value but didn't match the assumed return type. 332 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 333 * represents the double or float Infinity or NaN. 334 * @see Number#byteValue() 335 * @deprecated 2.3.0 in favor of {@link #getByteOrDefault(JsonKey)} */ 336 @Deprecated 337 public Byte getByteOrDefault(final String key, final byte defaultValue){ 338 Object returnable; 339 if(this.containsKey(key)){ 340 returnable = this.get(key); 341 }else{ 342 return defaultValue; 343 } 344 if(returnable == null){ 345 return null; 346 } 347 if(returnable instanceof String){ 348 /* A String can be used to construct a BigDecimal. */ 349 returnable = new BigDecimal((String)returnable); 350 } 351 return ((Number)returnable).byteValue(); 352 } 353 354 /** A convenience method that assumes there is a Collection at the given key. 355 * @param <T> the kind of collection to expect at the key. Note unless manually added, collection values will be a 356 * JsonArray. 357 * @param key representing where the value ought to be paired with. 358 * @return a Collection representing the value paired with the key. 359 * @throws ClassCastException if the value didn't match the assumed return type. 360 * @see JsonKey 361 * @since 2.3.0 to utilize JsonKey */ 362 @SuppressWarnings("unchecked") 363 public <T extends Collection<?>> T getCollection(final JsonKey key){ 364 /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will 365 * work. */ 366 return (T)this.get(key.getKey()); 367 } 368 369 /** A convenience method that assumes there is a Collection at the given key. 370 * @param <T> the kind of collection to expect at the key. Note unless manually added, collection values will be a 371 * JsonArray. 372 * @param key representing where the value ought to be stored at. 373 * @return the value stored at the key. 374 * @throws ClassCastException if the value didn't match the assumed return type. 375 * @deprecated 2.3.0 in favor of {@link #getCollection(JsonKey)} */ 376 @Deprecated 377 @SuppressWarnings("unchecked") 378 public <T extends Collection<?>> T getCollection(final String key){ 379 /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will 380 * work. */ 381 return (T)this.get(key); 382 } 383 384 /** A convenience method that assumes there is a Collection at the given key. 385 * @param <T> the kind of collection to expect at the key. Note unless manually added, collection values will be a 386 * JsonArray. 387 * @param key representing where the value ought to be paired with. 388 * @return a Collection representing the value paired with the key or JsonKey#getValue() if the key isn't present.. 389 * @throws ClassCastException if the value didn't match the assumed return type. 390 * @see JsonKey 391 * @since 2.3.0 to utilize JsonKey */ 392 @SuppressWarnings("unchecked") 393 public <T extends Collection<?>> T getCollectionOrDefault(final JsonKey key){ 394 /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will 395 * work. */ 396 Object returnable; 397 if(this.containsKey(key.getKey())){ 398 returnable = this.get(key.getKey()); 399 }else{ 400 returnable = key.getValue(); 401 } 402 return (T)returnable; 403 } 404 405 /** A convenience method that assumes there is a Collection at the given key. 406 * @param <T> the kind of collection to expect at the key. Note unless manually added, collection values will be a 407 * JsonArray. 408 * @param key representing where the value ought to be stored at. 409 * @param defaultValue representing what is returned when the key isn't in the JsonObject. 410 * @return the value stored at the key or the default provided if the key doesn't exist. 411 * @throws ClassCastException if there was a value but didn't match the assumed return type. 412 * @deprecated 2.3.0 in favor of {@link #getCollectionOrDefault(JsonKey)} */ 413 @Deprecated 414 @SuppressWarnings("unchecked") 415 public <T extends Collection<?>> T getCollectionOrDefault(final String key, final T defaultValue){ 416 /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will 417 * work. */ 418 Object returnable; 419 if(this.containsKey(key)){ 420 returnable = this.get(key); 421 }else{ 422 return defaultValue; 423 } 424 return (T)returnable; 425 } 426 427 /** A convenience method that assumes there is a Number or String value at the given key. 428 * @param key representing where the value ought to be paired with. 429 * @return a Double representing the value paired with the key (which may involve rounding or truncation). 430 * @throws ClassCastException if the value didn't match the assumed return type. 431 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 432 * represents the double or float Infinity or NaN. 433 * @see Number#doubleValue() 434 * @see JsonKey 435 * @since 2.3.0 to utilize JsonKey */ 436 public Double getDouble(final JsonKey key){ 437 Object returnable = this.get(key.getKey()); 438 if(returnable == null){ 439 return null; 440 } 441 if(returnable instanceof String){ 442 /* A String can be used to construct a BigDecimal. */ 443 returnable = new BigDecimal((String)returnable); 444 } 445 return ((Number)returnable).doubleValue(); 446 } 447 448 /** A convenience method that assumes there is a Number or String value at the given key. 449 * @param key representing where the value ought to be stored at. 450 * @return the value stored at the key (which may involve rounding or truncation). 451 * @throws ClassCastException if the value didn't match the assumed return type. 452 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 453 * represents the double or float Infinity or NaN. 454 * @see Number#doubleValue() 455 * @deprecated 2.3.0 in favor of {@link #getDouble(JsonKey)} */ 456 @Deprecated 457 public Double getDouble(final String key){ 458 Object returnable = this.get(key); 459 if(returnable == null){ 460 return null; 461 } 462 if(returnable instanceof String){ 463 /* A String can be used to construct a BigDecimal. */ 464 returnable = new BigDecimal((String)returnable); 465 } 466 return ((Number)returnable).doubleValue(); 467 } 468 469 /** A convenience method that assumes there is a Number or String value at the given key. 470 * @param key representing where the value ought to be paired with. 471 * @return a Double representing the value paired with the key or JsonKey#getValue() if the key isn't present (which 472 * may involve rounding or truncation). 473 * @throws ClassCastException if the value didn't match the assumed return type. 474 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 475 * represents the double or float Infinity or NaN. 476 * @see Number#doubleValue() 477 * @see JsonKey 478 * @since 2.3.0 to utilize JsonKey */ 479 public Double getDoubleOrDefault(final JsonKey key){ 480 Object returnable; 481 if(this.containsKey(key.getKey())){ 482 returnable = this.get(key.getKey()); 483 }else{ 484 returnable = key.getValue(); 485 } 486 if(returnable == null){ 487 return null; 488 } 489 if(returnable instanceof String){ 490 /* A String can be used to construct a BigDecimal. */ 491 returnable = new BigDecimal((String)returnable); 492 } 493 return ((Number)returnable).doubleValue(); 494 } 495 496 /** A convenience method that assumes there is a Number or String value at the given key. 497 * @param key representing where the value ought to be stored at. 498 * @param defaultValue representing what is returned when the key isn't in the JsonObject. 499 * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key 500 * doesn't exist. 501 * @throws ClassCastException if there was a value but didn't match the assumed return type. 502 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 503 * represents the double or float Infinity or NaN. 504 * @see Number#doubleValue() 505 * @deprecated 2.3.0 in favor of {@link #getDoubleOrDefault(JsonKey)} */ 506 @Deprecated 507 public Double getDoubleOrDefault(final String key, final double defaultValue){ 508 Object returnable; 509 if(this.containsKey(key)){ 510 returnable = this.get(key); 511 }else{ 512 return defaultValue; 513 } 514 if(returnable == null){ 515 return null; 516 } 517 if(returnable instanceof String){ 518 /* A String can be used to construct a BigDecimal. */ 519 returnable = new BigDecimal((String)returnable); 520 } 521 return ((Number)returnable).doubleValue(); 522 } 523 524 /** A convenience method that assumes there is a String value at the given key representing a fully qualified name 525 * in dot notation of an enum. 526 * @param key representing where the value ought to be paired with. 527 * @param <T> the Enum type the value at the key is expected to belong to. 528 * @return an Enum representing the value paired with the key. 529 * @throws ClassNotFoundException if the value was a String but the declaring enum type couldn't be determined with 530 * it. 531 * @throws ClassCastException if the element at the index was not a String or if the fully qualified enum name is of 532 * the wrong type. 533 * @throws IllegalArgumentException if an enum type was determined but it doesn't define an enum with the determined 534 * name. 535 * @see Enum#valueOf(Class, String) 536 * @see JsonKey 537 * @since 2.3.0 to utilize JsonKey 538 * @deprecated 2.3.0 Jsoner deprecated automatically serializing enums as Strings. */ 539 @Deprecated 540 @SuppressWarnings("unchecked") 541 public <T extends Enum<T>> T getEnum(final JsonKey key) throws ClassNotFoundException{ 542 /* Supressing the unchecked warning because the returnType is dynamically identified and could lead to a 543 * ClassCastException when returnType is cast to Class<T>, which is acceptable by the method's contract. */ 544 T returnable; 545 final String value; 546 final String[] splitValues; 547 final int numberOfSplitValues; 548 final StringBuilder returnTypeName; 549 final StringBuilder enumName; 550 final Class<T> returnType; 551 /* Make sure the value at the key is a String. */ 552 value = this.getString(key); 553 if(value == null){ 554 return null; 555 } 556 /* Get the package, class, and enum names. */ 557 splitValues = value.split("\\."); 558 numberOfSplitValues = splitValues.length; 559 returnTypeName = new StringBuilder(); 560 enumName = new StringBuilder(); 561 for(int i = 0; i < numberOfSplitValues; i++){ 562 if(i == (numberOfSplitValues - 1)){ 563 /* If it is the last split value then it should be the name of the Enum since dots are not allowed 564 * in enum names. */ 565 enumName.append(splitValues[i]); 566 }else if(i == (numberOfSplitValues - 2)){ 567 /* If it is the penultimate split value then it should be the end of the package/enum type and not 568 * need a dot appended to it. */ 569 returnTypeName.append(splitValues[i]); 570 }else{ 571 /* Must be part of the package/enum type and will need a dot appended to it since they got removed 572 * in the split. */ 573 returnTypeName.append(splitValues[i]); 574 returnTypeName.append("."); 575 } 576 } 577 /* Use the package/class and enum names to get the Enum<T>. */ 578 returnType = (Class<T>)Class.forName(returnTypeName.toString()); 579 returnable = Enum.valueOf(returnType, enumName.toString()); 580 return returnable; 581 } 582 583 /** A convenience method that assumes there is a String value at the given key representing a fully qualified name 584 * in dot notation of an enum. 585 * @param key representing where the value ought to be stored at. 586 * @param <T> the Enum type the value at the key is expected to belong to. 587 * @return the enum based on the string found at the key, or null if the value paired with the provided key is null. 588 * @throws ClassNotFoundException if the value was a String but the declaring enum type couldn't be determined with 589 * it. 590 * @throws ClassCastException if the element at the index was not a String or if the fully qualified enum name is of 591 * the wrong type. 592 * @throws IllegalArgumentException if an enum type was determined but it doesn't define an enum with the determined 593 * name. 594 * @see Enum#valueOf(Class, String) 595 * @deprecated 2.3.0 in favor of {@link #getEnum(JsonKey)} */ 596 @Deprecated 597 @SuppressWarnings("unchecked") 598 public <T extends Enum<T>> T getEnum(final String key) throws ClassNotFoundException{ 599 /* Supressing the unchecked warning because the returnType is dynamically identified and could lead to a 600 * ClassCastException when returnType is cast to Class<T>, which is expected by the method's contract. */ 601 T returnable; 602 final String value; 603 final String[] splitValues; 604 final int numberOfSplitValues; 605 final StringBuilder returnTypeName; 606 final StringBuilder enumName; 607 final Class<T> returnType; 608 /* Make sure the value at the key is a String. */ 609 value = this.getStringOrDefault(key, ""); 610 if(value == null){ 611 return null; 612 } 613 /* Get the package, class, and enum names. */ 614 splitValues = value.split("\\."); 615 numberOfSplitValues = splitValues.length; 616 returnTypeName = new StringBuilder(); 617 enumName = new StringBuilder(); 618 for(int i = 0; i < numberOfSplitValues; i++){ 619 if(i == (numberOfSplitValues - 1)){ 620 /* If it is the last split value then it should be the name of the Enum since dots are not allowed 621 * in enum names. */ 622 enumName.append(splitValues[i]); 623 }else if(i == (numberOfSplitValues - 2)){ 624 /* If it is the penultimate split value then it should be the end of the package/enum type and not 625 * need a dot appended to it. */ 626 returnTypeName.append(splitValues[i]); 627 }else{ 628 /* Must be part of the package/enum type and will need a dot appended to it since they got removed 629 * in the split. */ 630 returnTypeName.append(splitValues[i]); 631 returnTypeName.append("."); 632 } 633 } 634 /* Use the package/class and enum names to get the Enum<T>. */ 635 returnType = (Class<T>)Class.forName(returnTypeName.toString()); 636 returnable = Enum.valueOf(returnType, enumName.toString()); 637 return returnable; 638 } 639 640 /** A convenience method that assumes there is a String value at the given key representing a fully qualified name 641 * in dot notation of an enum. 642 * @param key representing where the value ought to be paired with. 643 * @param <T> the Enum type the value at the key is expected to belong to. 644 * @return an Enum representing the value paired with the key or JsonKey#getValue() if the key isn't present. 645 * @throws ClassNotFoundException if the value was a String but the declaring enum type couldn't be determined with 646 * it. 647 * @throws ClassCastException if the element at the index was not a String or if the fully qualified enum name is of 648 * the wrong type. 649 * @throws IllegalArgumentException if an enum type was determined but it doesn't define an enum with the determined 650 * name. 651 * @see Enum#valueOf(Class, String) 652 * @see JsonKey 653 * @since 2.3.0 to utilize JsonKey 654 * @deprecated 2.3.0 Jsoner deprecated automatically serializing enums as Strings. */ 655 @Deprecated 656 @SuppressWarnings("unchecked") 657 public <T extends Enum<T>> T getEnumOrDefault(final JsonKey key) throws ClassNotFoundException{ 658 /* Supressing the unchecked warning because the returnType is dynamically identified and could lead to a 659 * ClassCastException when returnType is cast to Class<T>, which is acceptable by the method's contract. */ 660 T returnable; 661 final String value; 662 final String[] splitValues; 663 final int numberOfSplitValues; 664 final StringBuilder returnTypeName; 665 final StringBuilder enumName; 666 final Class<T> returnType; 667 /* Check to make sure the key is there. */ 668 if(this.containsKey(key)){ 669 /* Make sure the value at the key is a String. */ 670 value = this.getStringOrDefault(key.getKey(), ""); 671 if(value == null){ 672 return null; 673 } 674 /* Get the package, class, and enum names. */ 675 splitValues = value.split("\\."); 676 numberOfSplitValues = splitValues.length; 677 returnTypeName = new StringBuilder(); 678 enumName = new StringBuilder(); 679 for(int i = 0; i < numberOfSplitValues; i++){ 680 if(i == (numberOfSplitValues - 1)){ 681 /* If it is the last split value then it should be the name of the Enum since dots are not allowed 682 * in enum names. */ 683 enumName.append(splitValues[i]); 684 }else if(i == (numberOfSplitValues - 2)){ 685 /* If it is the penultimate split value then it should be the end of the package/enum type and not 686 * need a dot appended to it. */ 687 returnTypeName.append(splitValues[i]); 688 }else{ 689 /* Must be part of the package/enum type and will need a dot appended to it since they got removed 690 * in the split. */ 691 returnTypeName.append(splitValues[i]); 692 returnTypeName.append("."); 693 } 694 } 695 /* Use the package/class and enum names to get the Enum<T>. */ 696 returnType = (Class<T>)Class.forName(returnTypeName.toString()); 697 returnable = Enum.valueOf(returnType, enumName.toString()); 698 }else{ 699 /* It wasn't there and according to the method's contract we return the default value. */ 700 returnable = (T)key.getValue(); 701 } 702 return returnable; 703 } 704 705 /** A convenience method that assumes there is a String value at the given key representing a fully qualified name 706 * in dot notation of an enum. 707 * @param key representing where the value ought to be stored at. 708 * @param defaultValue representing what is returned when the key isn't in the JsonObject. 709 * @param <T> the Enum type the value at the key is expected to belong to. 710 * @return the enum based on the string found at the key, or the defaultValue provided if the key doesn't exist, or 711 * null if the value paired with provided key is null. 712 * @throws ClassNotFoundException if the value was a String but the declaring enum type couldn't be determined with 713 * it. 714 * @throws ClassCastException if the element at the index was not a String or if the fully qualified enum name is of 715 * the wrong type. 716 * @throws IllegalArgumentException if an enum type was determined but it doesn't define an enum with the determined 717 * name. 718 * @see Enum#valueOf(Class, String) 719 * @deprecated 2.3.0 in favor of {@link #getEnumOrDefault(JsonKey)} */ 720 @Deprecated 721 @SuppressWarnings("unchecked") 722 public <T extends Enum<T>> T getEnumOrDefault(final String key, final T defaultValue) throws ClassNotFoundException{ 723 /* Supressing the unchecked warning because the returnType is dynamically identified and could lead to a 724 * ClassCastException when returnType is cast to Class<T>, which is expected by the method's contract. */ 725 T returnable; 726 final String value; 727 final String[] splitValues; 728 final int numberOfSplitValues; 729 final StringBuilder returnTypeName; 730 final StringBuilder enumName; 731 final Class<T> returnType; 732 /* Check to make sure the key wasn't actually there and wasn't coincidentally the defaulted String as its 733 * value. */ 734 if(this.containsKey(key)){ 735 /* Make sure the value at the key is a String. */ 736 value = this.getStringOrDefault(key, ""); 737 if(value == null){ 738 return null; 739 } 740 /* Get the package, class, and enum names. */ 741 splitValues = value.split("\\."); 742 numberOfSplitValues = splitValues.length; 743 returnTypeName = new StringBuilder(); 744 enumName = new StringBuilder(); 745 for(int i = 0; i < numberOfSplitValues; i++){ 746 if(i == (numberOfSplitValues - 1)){ 747 /* If it is the last split value then it should be the name of the Enum since dots are not allowed 748 * in enum names. */ 749 enumName.append(splitValues[i]); 750 }else if(i == (numberOfSplitValues - 2)){ 751 /* If it is the penultimate split value then it should be the end of the package/enum type and not 752 * need a dot appended to it. */ 753 returnTypeName.append(splitValues[i]); 754 }else{ 755 /* Must be part of the package/enum type and will need a dot appended to it since they got removed 756 * in the split. */ 757 returnTypeName.append(splitValues[i]); 758 returnTypeName.append("."); 759 } 760 } 761 /* Use the package/class and enum names to get the Enum<T>. */ 762 returnType = (Class<T>)Class.forName(returnTypeName.toString()); 763 returnable = Enum.valueOf(returnType, enumName.toString()); 764 }else{ 765 /* It wasn't there and according to the method's contract we return the default value. */ 766 return defaultValue; 767 } 768 return returnable; 769 } 770 771 /** A convenience method that assumes there is a Number or String value at the given key. 772 * @param key representing where the value ought to be paired with. 773 * @return a Float representing the value paired with the key (which may involve rounding or truncation). 774 * @throws ClassCastException if the value didn't match the assumed return type. 775 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 776 * represents the double or float Infinity or NaN. 777 * @see Number#floatValue() 778 * @see JsonKey 779 * @since 2.3.0 to utilize JsonKey */ 780 public Float getFloat(final JsonKey key){ 781 Object returnable = this.get(key.getKey()); 782 if(returnable == null){ 783 return null; 784 } 785 if(returnable instanceof String){ 786 /* A String can be used to construct a BigDecimal. */ 787 returnable = new BigDecimal((String)returnable); 788 } 789 return ((Number)returnable).floatValue(); 790 } 791 792 /** A convenience method that assumes there is a Number or String value at the given key. 793 * @param key representing where the value ought to be stored at. 794 * @return the value stored at the key (which may involve rounding or truncation). 795 * @throws ClassCastException if the value didn't match the assumed return type. 796 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 797 * represents the double or float Infinity or NaN. 798 * @see Number#floatValue() 799 * @deprecated 2.3.0 in favor of {@link #getFloat(JsonKey)} */ 800 @Deprecated 801 public Float getFloat(final String key){ 802 Object returnable = this.get(key); 803 if(returnable == null){ 804 return null; 805 } 806 if(returnable instanceof String){ 807 /* A String can be used to construct a BigDecimal. */ 808 returnable = new BigDecimal((String)returnable); 809 } 810 return ((Number)returnable).floatValue(); 811 } 812 813 /** A convenience method that assumes there is a Number or String value at the given key. 814 * @param key representing where the value ought to be paired with. 815 * @return a Float representing the value paired with the key or JsonKey#getValue() if the key isn't present (which 816 * may involve rounding or truncation). 817 * @throws ClassCastException if the value didn't match the assumed return type. 818 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 819 * represents the double or float Infinity or NaN. 820 * @see Number#floatValue() 821 * @see JsonKey 822 * @since 2.3.0 to utilize JsonKey */ 823 public Float getFloatOrDefault(final JsonKey key){ 824 Object returnable; 825 if(this.containsKey(key.getKey())){ 826 returnable = this.get(key.getKey()); 827 }else{ 828 returnable = key.getValue(); 829 } 830 if(returnable == null){ 831 return null; 832 } 833 if(returnable instanceof String){ 834 /* A String can be used to construct a BigDecimal. */ 835 returnable = new BigDecimal((String)returnable); 836 } 837 return ((Number)returnable).floatValue(); 838 } 839 840 /** A convenience method that assumes there is a Number or String value at the given key. 841 * @param key representing where the value ought to be stored at. 842 * @param defaultValue representing what is returned when the key isn't in the JsonObject. 843 * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key 844 * doesn't exist. 845 * @throws ClassCastException if there was a value but didn't match the assumed return type. 846 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 847 * represents the double or float Infinity or NaN. 848 * @see Number#floatValue() 849 * @deprecated 2.3.0 in favor of {@link #getFloatOrDefault(JsonKey)} */ 850 @Deprecated 851 public Float getFloatOrDefault(final String key, final float defaultValue){ 852 Object returnable; 853 if(this.containsKey(key)){ 854 returnable = this.get(key); 855 }else{ 856 return defaultValue; 857 } 858 if(returnable == null){ 859 return null; 860 } 861 if(returnable instanceof String){ 862 /* A String can be used to construct a BigDecimal. */ 863 returnable = new BigDecimal((String)returnable); 864 } 865 return ((Number)returnable).floatValue(); 866 } 867 868 /** A convenience method that assumes there is a Number or String value at the given key. 869 * @param key representing where the value ought to be paired with. 870 * @return an Integer representing the value paired with the key (which may involve rounding or truncation). 871 * @throws ClassCastException if the value didn't match the assumed return type. 872 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 873 * represents the double or float Infinity or NaN. 874 * @see Number#intValue() 875 * @see JsonKey 876 * @since 2.3.0 to utilize JsonKey */ 877 public Integer getInteger(final JsonKey key){ 878 Object returnable = this.get(key.getKey()); 879 if(returnable == null){ 880 return null; 881 } 882 if(returnable instanceof String){ 883 /* A String can be used to construct a BigDecimal. */ 884 returnable = new BigDecimal((String)returnable); 885 } 886 return ((Number)returnable).intValue(); 887 } 888 889 /** A convenience method that assumes there is a Number or String value at the given key. 890 * @param key representing where the value ought to be stored at. 891 * @return the value stored at the key (which may involve rounding or truncation). 892 * @throws ClassCastException if the value didn't match the assumed return type. 893 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 894 * represents the double or float Infinity or NaN. 895 * @see Number#intValue() 896 * @deprecated 2.3.0 in favor of {@link #getInteger(JsonKey)} */ 897 @Deprecated 898 public Integer getInteger(final String key){ 899 Object returnable = this.get(key); 900 if(returnable == null){ 901 return null; 902 } 903 if(returnable instanceof String){ 904 /* A String can be used to construct a BigDecimal. */ 905 returnable = new BigDecimal((String)returnable); 906 } 907 return ((Number)returnable).intValue(); 908 } 909 910 /** A convenience method that assumes there is a Number or String value at the given key. 911 * @param key representing where the value ought to be paired with. 912 * @return an Integer representing the value paired with the key or JsonKey#getValue() if the key isn't present 913 * (which may involve rounding or truncation). 914 * @throws ClassCastException if the value didn't match the assumed return type. 915 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 916 * represents the double or float Infinity or NaN. 917 * @see Number#intValue() 918 * @see JsonKey 919 * @since 2.3.0 to utilize JsonKey */ 920 public Integer getIntegerOrDefault(final JsonKey key){ 921 Object returnable; 922 if(this.containsKey(key.getKey())){ 923 returnable = this.get(key.getKey()); 924 }else{ 925 returnable = key.getValue(); 926 } 927 if(returnable == null){ 928 return null; 929 } 930 if(returnable instanceof String){ 931 /* A String can be used to construct a BigDecimal. */ 932 returnable = new BigDecimal((String)returnable); 933 } 934 return ((Number)returnable).intValue(); 935 } 936 937 /** A convenience method that assumes there is a Number or String value at the given key. 938 * @param key representing where the value ought to be stored at. 939 * @param defaultValue representing what is returned when the key isn't in the JsonObject. 940 * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key 941 * doesn't exist. 942 * @throws ClassCastException if there was a value but didn't match the assumed return type. 943 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 944 * represents the double or float Infinity or NaN. 945 * @see Number#intValue() 946 * @deprecated 2.3.0 in favor of {@link #getIntegerOrDefault(JsonKey)} */ 947 @Deprecated 948 public Integer getIntegerOrDefault(final String key, final int defaultValue){ 949 Object returnable; 950 if(this.containsKey(key)){ 951 returnable = this.get(key); 952 }else{ 953 return defaultValue; 954 } 955 if(returnable == null){ 956 return null; 957 } 958 if(returnable instanceof String){ 959 /* A String can be used to construct a BigDecimal. */ 960 returnable = new BigDecimal((String)returnable); 961 } 962 return ((Number)returnable).intValue(); 963 } 964 965 /** A convenience method that assumes there is a Number or String value at the given key. 966 * @param key representing where the value ought to be paired with. 967 * @return a Long representing the value paired with the key (which may involve rounding or truncation). 968 * @throws ClassCastException if the value didn't match the assumed return type. 969 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 970 * represents the double or float Infinity or NaN. 971 * @see Number#longValue() 972 * @see JsonKey 973 * @since 2.3.0 to utilize JsonKey */ 974 public Long getLong(final JsonKey key){ 975 Object returnable = this.get(key.getKey()); 976 if(returnable == null){ 977 return null; 978 } 979 if(returnable instanceof String){ 980 /* A String can be used to construct a BigDecimal. */ 981 returnable = new BigDecimal((String)returnable); 982 } 983 return ((Number)returnable).longValue(); 984 } 985 986 /** A convenience method that assumes there is a Number or String value at the given key. 987 * @param key representing where the value ought to be stored at. 988 * @return the value stored at the key (which may involve rounding or truncation). 989 * @throws ClassCastException if the value didn't match the assumed return type. 990 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 991 * represents the double or float Infinity or NaN. 992 * @see Number#longValue() 993 * @deprecated 2.3.0 in favor of {@link #getLong(JsonKey)} */ 994 @Deprecated 995 public Long getLong(final String key){ 996 Object returnable = this.get(key); 997 if(returnable == null){ 998 return null; 999 } 1000 if(returnable instanceof String){ 1001 /* A String can be used to construct a BigDecimal. */ 1002 returnable = new BigDecimal((String)returnable); 1003 } 1004 return ((Number)returnable).longValue(); 1005 } 1006 1007 /** A convenience method that assumes there is a Number or String value at the given key. 1008 * @param key representing where the value ought to be paired with. 1009 * @return a Long representing the value paired with the key or JsonKey#getValue() if the key isn't present (which 1010 * may involve rounding or truncation). 1011 * @throws ClassCastException if the value didn't match the assumed return type. 1012 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 1013 * represents the double or float Infinity or NaN. 1014 * @see Number#longValue() 1015 * @see JsonKey 1016 * @since 2.3.0 to utilize JsonKey */ 1017 public Long getLongOrDefault(final JsonKey key){ 1018 Object returnable; 1019 if(this.containsKey(key.getKey())){ 1020 returnable = this.get(key.getKey()); 1021 }else{ 1022 returnable = key.getValue(); 1023 } 1024 if(returnable == null){ 1025 return null; 1026 } 1027 if(returnable instanceof String){ 1028 /* A String can be used to construct a BigDecimal. */ 1029 returnable = new BigDecimal((String)returnable); 1030 } 1031 return ((Number)returnable).longValue(); 1032 } 1033 1034 /** A convenience method that assumes there is a Number or String value at the given key. 1035 * @param key representing where the value ought to be stored at. 1036 * @param defaultValue representing what is returned when the key isn't in the JsonObject. 1037 * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key 1038 * doesn't exist. 1039 * @throws ClassCastException if there was a value but didn't match the assumed return type. 1040 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 1041 * represents the double or float Infinity or NaN. 1042 * @see Number#longValue() 1043 * @deprecated 2.3.0 in favor of {@link #getLongOrDefault(JsonKey)} */ 1044 @Deprecated 1045 public Long getLongOrDefault(final String key, final long defaultValue){ 1046 Object returnable; 1047 if(this.containsKey(key)){ 1048 returnable = this.get(key); 1049 }else{ 1050 return defaultValue; 1051 } 1052 if(returnable == null){ 1053 return null; 1054 } 1055 if(returnable instanceof String){ 1056 /* A String can be used to construct a BigDecimal. */ 1057 returnable = new BigDecimal((String)returnable); 1058 } 1059 return ((Number)returnable).longValue(); 1060 } 1061 1062 /** A convenience method that assumes there is a Map at the given key. 1063 * @param <T> the kind of map to expect at the key. Note unless manually added, Map values will be a JsonObject. 1064 * @param key representing where the value ought to be paired with. 1065 * @return a Map representing the value paired with the key. 1066 * @throws ClassCastException if the value didn't match the assumed return type. 1067 * @see JsonKey 1068 * @since 2.3.0 to utilize JsonKey */ 1069 @SuppressWarnings("unchecked") 1070 public <T extends Map<?, ?>> T getMap(final JsonKey key){ 1071 /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will 1072 * work. */ 1073 return (T)this.get(key.getKey()); 1074 } 1075 1076 /** A convenience method that assumes there is a Map at the given key. 1077 * @param <T> the kind of map to expect at the key. Note unless manually added, Map values will be a JsonObject. 1078 * @param key representing where the value ought to be stored at. 1079 * @return the value stored at the key. 1080 * @throws ClassCastException if the value didn't match the assumed return type. 1081 * @deprecated 2.3.0 in favor of {@link #getMap(JsonKey)} */ 1082 @Deprecated 1083 @SuppressWarnings("unchecked") 1084 public <T extends Map<?, ?>> T getMap(final String key){ 1085 /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will 1086 * work. */ 1087 return (T)this.get(key); 1088 } 1089 1090 /** A convenience method that assumes there is a Map at the given key. 1091 * @param <T> the kind of map to expect at the key. Note unless manually added, Map values will be a JsonObject. 1092 * @param key representing where the value ought to be paired with. 1093 * @return a Map representing the value paired with the key or JsonKey#getValue() if the key isn't present. 1094 * @throws ClassCastException if the value didn't match the assumed return type. 1095 * @see JsonKey 1096 * @since 2.3.0 to utilize JsonKey */ 1097 @SuppressWarnings("unchecked") 1098 public <T extends Map<?, ?>> T getMapOrDefault(final JsonKey key){ 1099 /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will 1100 * work. */ 1101 Object returnable; 1102 if(this.containsKey(key.getKey())){ 1103 returnable = this.get(key.getKey()); 1104 }else{ 1105 returnable = key.getValue(); 1106 } 1107 return (T)returnable; 1108 } 1109 1110 /** A convenience method that assumes there is a Map at the given key. 1111 * @param <T> the kind of map to expect at the key. Note unless manually added, Map values will be a JsonObject. 1112 * @param key representing where the value ought to be stored at. 1113 * @param defaultValue representing what is returned when the key isn't in the JsonObject. 1114 * @return the value stored at the key or the default provided if the key doesn't exist. 1115 * @throws ClassCastException if there was a value but didn't match the assumed return type. 1116 * @deprecated 2.3.0 in favor of {@link #getMapOrDefault(JsonKey)} */ 1117 @Deprecated 1118 @SuppressWarnings("unchecked") 1119 public <T extends Map<?, ?>> T getMapOrDefault(final String key, final T defaultValue){ 1120 /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will 1121 * work. */ 1122 Object returnable; 1123 if(this.containsKey(key)){ 1124 returnable = this.get(key); 1125 }else{ 1126 returnable = defaultValue; 1127 } 1128 return (T)returnable; 1129 } 1130 1131 /** A convenience method that assumes there is a Number or String value at the given key. 1132 * @param key representing where the value ought to be paired with. 1133 * @return a Short representing the value paired with the key (which may involve rounding or truncation). 1134 * @throws ClassCastException if the value didn't match the assumed return type. 1135 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 1136 * represents the double or float Infinity or NaN. 1137 * @see Number#shortValue() 1138 * @see JsonKey 1139 * @since 2.3.0 to utilize JsonKey */ 1140 public Short getShort(final JsonKey key){ 1141 Object returnable = this.get(key.getKey()); 1142 if(returnable == null){ 1143 return null; 1144 } 1145 if(returnable instanceof String){ 1146 /* A String can be used to construct a BigDecimal. */ 1147 returnable = new BigDecimal((String)returnable); 1148 } 1149 return ((Number)returnable).shortValue(); 1150 } 1151 1152 /** A convenience method that assumes there is a Number or String value at the given key. 1153 * @param key representing where the value ought to be stored at. 1154 * @return the value stored at the key (which may involve rounding or truncation). 1155 * @throws ClassCastException if the value didn't match the assumed return type. 1156 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 1157 * represents the double or float Infinity or NaN. 1158 * @see Number#shortValue() 1159 * @deprecated 2.3.0 in favor of {@link #getShort(JsonKey)} */ 1160 @Deprecated 1161 public Short getShort(final String key){ 1162 Object returnable = this.get(key); 1163 if(returnable == null){ 1164 return null; 1165 } 1166 if(returnable instanceof String){ 1167 /* A String can be used to construct a BigDecimal. */ 1168 returnable = new BigDecimal((String)returnable); 1169 } 1170 return ((Number)returnable).shortValue(); 1171 } 1172 1173 /** A convenience method that assumes there is a Number or String value at the given key. 1174 * @param key representing where the value ought to be paired with. 1175 * @return a Short representing the value paired with the key or JsonKey#getValue() if the key isn't present (which 1176 * may involve rounding or truncation). 1177 * @throws ClassCastException if the value didn't match the assumed return type. 1178 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 1179 * represents the double or float Infinity or NaN. 1180 * @see Number#shortValue() 1181 * @see JsonKey 1182 * @since 2.3.0 to utilize JsonKey */ 1183 public Short getShortOrDefault(final JsonKey key){ 1184 Object returnable; 1185 if(this.containsKey(key.getKey())){ 1186 returnable = this.get(key.getKey()); 1187 }else{ 1188 returnable = key.getValue(); 1189 } 1190 if(returnable == null){ 1191 return null; 1192 } 1193 if(returnable instanceof String){ 1194 /* A String can be used to construct a BigDecimal. */ 1195 returnable = new BigDecimal((String)returnable); 1196 } 1197 return ((Number)returnable).shortValue(); 1198 } 1199 1200 /** A convenience method that assumes there is a Number or String value at the given key. 1201 * @param key representing where the value ought to be stored at. 1202 * @param defaultValue representing what is returned when the key isn't in the JsonObject. 1203 * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key 1204 * doesn't exist. 1205 * @throws ClassCastException if there was a value but didn't match the assumed return type. 1206 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number 1207 * represents the double or float Infinity or NaN. 1208 * @see Number#shortValue() 1209 * @deprecated 2.3.0 in favor of {@link #getShortOrDefault(JsonKey)} */ 1210 @Deprecated 1211 public Short getShortOrDefault(final String key, final short defaultValue){ 1212 Object returnable; 1213 if(this.containsKey(key)){ 1214 returnable = this.get(key); 1215 }else{ 1216 return defaultValue; 1217 } 1218 if(returnable == null){ 1219 return null; 1220 } 1221 if(returnable instanceof String){ 1222 /* A String can be used to construct a BigDecimal. */ 1223 returnable = new BigDecimal((String)returnable); 1224 } 1225 return ((Number)returnable).shortValue(); 1226 } 1227 1228 /** A convenience method that assumes there is a Boolean, Number, or String value at the given key. 1229 * @param key representing where the value ought to be paired with. 1230 * @return a String representing the value paired with the key. 1231 * @throws ClassCastException if the value didn't match the assumed return type. 1232 * @see JsonKey 1233 * @since 2.3.0 to utilize JsonKey */ 1234 public String getString(final JsonKey key){ 1235 Object returnable = this.get(key.getKey()); 1236 if(returnable instanceof Boolean){ 1237 returnable = returnable.toString(); 1238 }else if(returnable instanceof Number){ 1239 returnable = returnable.toString(); 1240 } 1241 return (String)returnable; 1242 } 1243 1244 /** A convenience method that assumes there is a Boolean, Number, or String value at the given key. 1245 * @param key representing where the value ought to be stored at. 1246 * @return the value stored at the key. 1247 * @throws ClassCastException if the value didn't match the assumed return type. 1248 * @deprecated 2.3.0 in favor of {@link #getString(JsonKey)} */ 1249 @Deprecated 1250 public String getString(final String key){ 1251 Object returnable = this.get(key); 1252 if(returnable instanceof Boolean){ 1253 returnable = returnable.toString(); 1254 }else if(returnable instanceof Number){ 1255 returnable = returnable.toString(); 1256 } 1257 return (String)returnable; 1258 } 1259 1260 /** A convenience method that assumes there is a Boolean, Number, or String value at the given key. 1261 * @param key representing where the value ought to be paired with. 1262 * @return a String representing the value paired with the key or JsonKey#getValue() if the key isn't present. 1263 * @throws ClassCastException if the value didn't match the assumed return type. 1264 * @see JsonKey 1265 * @since 2.3.0 to utilize JsonKey */ 1266 public String getStringOrDefault(final JsonKey key){ 1267 Object returnable; 1268 if(this.containsKey(key.getKey())){ 1269 returnable = this.get(key.getKey()); 1270 }else{ 1271 returnable = key.getValue(); 1272 } 1273 if(returnable instanceof Boolean){ 1274 returnable = returnable.toString(); 1275 }else if(returnable instanceof Number){ 1276 returnable = returnable.toString(); 1277 } 1278 return (String)returnable; 1279 } 1280 1281 /** A convenience method that assumes there is a Boolean, Number, or String value at the given key. 1282 * @param key representing where the value ought to be stored at. 1283 * @param defaultValue representing what is returned when the key isn't in the JsonObject. 1284 * @return the value stored at the key or the default provided if the key doesn't exist. 1285 * @throws ClassCastException if there was a value but didn't match the assumed return type. 1286 * @deprecated 2.3.0 in favor of {@link #getStringOrDefault(JsonKey)} */ 1287 @Deprecated 1288 public String getStringOrDefault(final String key, final String defaultValue){ 1289 Object returnable; 1290 if(this.containsKey(key)){ 1291 returnable = this.get(key); 1292 }else{ 1293 return defaultValue; 1294 } 1295 if(returnable instanceof Boolean){ 1296 returnable = returnable.toString(); 1297 }else if(returnable instanceof Number){ 1298 returnable = returnable.toString(); 1299 } 1300 return (String)returnable; 1301 } 1302 1303 /* (non-Javadoc) 1304 * @see org.json.simple.Jsonable#asJsonString() */ 1305 @Override 1306 public String toJson(){ 1307 final StringWriter writable = new StringWriter(); 1308 try{ 1309 this.toJson(writable); 1310 }catch(final IOException caught){ 1311 /* See java.io.StringWriter. */ 1312 } 1313 return writable.toString(); 1314 } 1315 1316 /* (non-Javadoc) 1317 * @see org.json.simple.Jsonable#toJsonString(java.io.Writer) */ 1318 @Override 1319 public void toJson(final Writer writable) throws IOException{ 1320 /* Writes the map in JSON object format. */ 1321 boolean isFirstEntry = true; 1322 final Iterator<Map.Entry<String, Object>> entries = this.entrySet().iterator(); 1323 writable.write('{'); 1324 while(entries.hasNext()){ 1325 if(isFirstEntry){ 1326 isFirstEntry = false; 1327 }else{ 1328 writable.write(','); 1329 } 1330 final Map.Entry<String, Object> entry = entries.next(); 1331 writable.write(Jsoner.serialize(entry.getKey())); 1332 writable.write(':'); 1333 writable.write(Jsoner.serialize(entry.getValue())); 1334 } 1335 writable.write('}'); 1336 } 1337}