001/* 002 * ============================================================================ 003 * Copyright © 2002-2026 by Thomas Thrien. 004 * All Rights Reserved. 005 * ============================================================================ 006 * Licensed to the public under the agreements of the GNU Lesser General Public 007 * License, version 3.0 (the "License"). You may obtain a copy of the License at 008 * 009 * http://www.gnu.org/licenses/lgpl.html 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 014 * License for the specific language governing permissions and limitations 015 * under the License. 016 */ 017 018package org.tquadrat.foundation.jsonbuilder; 019 020import static org.apiguardian.api.API.Status.STABLE; 021import static org.tquadrat.foundation.jsonbuilder.JSONLiteral.FALSE; 022import static org.tquadrat.foundation.jsonbuilder.JSONLiteral.TRUE; 023 024import java.math.BigDecimal; 025import java.math.BigInteger; 026import java.util.Optional; 027import java.util.SequencedCollection; 028 029import org.apiguardian.api.API; 030import org.tquadrat.foundation.annotation.ClassVersion; 031import org.tquadrat.foundation.jsonbuilder.internal.JSONObjectImpl; 032import org.tquadrat.foundation.lang.value.Dimension; 033import org.tquadrat.foundation.lang.value.DimensionedValue; 034 035/** 036 * <p>{@summary The definition of a JSON object.}</p> 037 * 038 * @extauthor Thomas Thrien - thomas.thrien@tquadrat.org 039 * @version $Id: JSONObject.java 1258 2026-06-04 18:33:06Z tquadrat $ 040 * @since 0.25.0 041 * 042 * @UMLGraph.link 043 */ 044@SuppressWarnings( "ClassWithTooManyMethods" ) 045@ClassVersion( sourceVersion = "$Id: JSONObject.java 1258 2026-06-04 18:33:06Z tquadrat $" ) 046@API( status = STABLE, since = "0.25.0" ) 047public sealed interface JSONObject extends Iterable<JSONValue>, JSONValue 048 permits JSONObjectImpl 049{ 050 /*---------*\ 051 ====** Methods **========================================================== 052 \*---------*/ 053 /** 054 * <p>{@summary Checks if a specified member is present as a child of this 055 * object.} This will not test if that child is the JSON literal 056 * {@null}, This needs to be tested separately.</p> 057 * 058 * @param name The name of the member to check for. 059 * @return {@true} if there is a member with the given name, 060 * {@false} if not. 061 */ 062 public boolean contains( final String name ); 063 064 /** 065 * <p>{@summary Returns the value of the member with the specified name in 066 * this object.}</p> 067 * 068 * @param name The name of the member whose value is to be returned. 069 * @return An instance of 070 * {@link Optional} 071 * that holds the value. 072 */ 073 public Optional<JSONValue> get( final String name ); 074 075 /** 076 * <p>{@summary Convenience method that returns the value with the 077 * specified name as a 078 * {@link JSONArray}.}</p> 079 * 080 * @param name The name of the member whose value is to be returned. 081 * @param defaultValue The value to be returned if the requested 082 * member is missing; can be {@null}. 083 * @return The value of the member with the specified name, or the given 084 * default value if this object does not contain a member with that 085 * name. 086 * @throws IllegalStateException The member exists, but it is not a 087 * JSON Array. 088 */ 089 public default JSONArray getArray( final String name, final JSONArray defaultValue ) throws IllegalStateException 090 { 091 final var retValue = get( name ).map( JSONValue::asArray ).orElse( defaultValue ); 092 093 //---* Done *---------------------------------------------------------- 094 return retValue; 095 } // getArray() 096 097 /** 098 * <p>{@summary Convenience method that returns the value with the 099 * specified name as a 100 * {@link BigDecimal}.}</p> 101 * 102 * @param name The name of the member whose value is to be returned. 103 * @param defaultValue The value to be returned if the requested 104 * member is missing; can be {@null}. 105 * @return The value of the member with the specified name, or the given 106 * default value if this object does not contain a member with that 107 * name. 108 * @throws IllegalStateException The member exists, but it is not a 109 * number. 110 * @throws NumberFormatException The member exists, and it is a number, 111 * but cannot be parsed to a valid {@code BigDecimal}. 112 */ 113 public default BigDecimal getBigDecimal( final String name, final BigDecimal defaultValue ) throws IllegalStateException, NumberFormatException 114 { 115 var retValue = defaultValue; 116 final var value = get( name ); 117 if( value.isPresent() ) 118 { 119 final var number = value.get().asNumber(); 120 retValue = number.getBigDecimal(); 121 } 122 123 //---* Done *---------------------------------------------------------- 124 return retValue; 125 } // getBigDecimal() 126 127 /** 128 * <p>{@summary Convenience method that returns the value with the 129 * specified name as a 130 * {@link BigInteger}.}</p> 131 * 132 * @param name The name of the member whose value is to be returned. 133 * @param defaultValue The value to be returned if the requested 134 * member is missing; can be {@null}. 135 * @return The value of the member with the specified name, or the given 136 * default value if this object does not contain a member with that 137 * name. 138 * @throws IllegalStateException The member exists, but it is not a 139 * number. 140 * @throws NumberFormatException The member exists, and it is a number, 141 * but cannot be parsed to a valid {@code BigInteger}. 142 */ 143 public default BigInteger getBigInteger( final String name, final BigInteger defaultValue ) throws IllegalStateException, NumberFormatException 144 { 145 var retValue = defaultValue; 146 final var value = get( name ); 147 if( value.isPresent() ) 148 { 149 final var number = value.get().asNumber(); 150 retValue = number.getBigInteger(); 151 } 152 153 //---* Done *---------------------------------------------------------- 154 return retValue; 155 } // getBigInteger() 156 157 /** 158 * <p>{@summary Convenience method that returns the value with the 159 * specified name as a {@code boolean}.}</p> 160 * 161 * @param name The name of the member whose value is to be returned. 162 * @param defaultValue The value to be returned if the requested 163 * member is missing. 164 * @return The value of the member with the specified name, or the given 165 * default value if this object does not contain a member with that 166 * name. 167 * @throws IllegalStateException The member exists, but it is not a 168 * boolean. 169 */ 170 @SuppressWarnings( "BooleanMethodNameMustStartWithQuestion" ) 171 public default boolean getBoolean( final String name, final boolean defaultValue ) throws IllegalStateException 172 { 173 var retValue = defaultValue; 174 final var value = get( name ); 175 if( value.isPresent() ) 176 { 177 final var flag = value.get().asBoolean(); 178 retValue = flag.isTrue(); 179 } 180 181 //---* Done *---------------------------------------------------------- 182 return retValue; 183 } // getBoolean() 184 185 /** 186 * <p>{@summary Convenience method that returns the value with the 187 * specified name as a {@code double}.}</p> 188 * 189 * @param name The name of the member whose value is to be returned. 190 * @param defaultValue The value to be returned if the requested 191 * member is missing. 192 * @return The value of the member with the specified name, or the given 193 * default value if this object does not contain a member with that 194 * name. 195 * @throws IllegalStateException The member exists, but it is not a 196 * number. 197 * @throws NumberFormatException The member exists, and it is a number, 198 * but cannot be parsed to a valid {@code double}. 199 */ 200 public default double getDouble( final String name, final double defaultValue ) throws IllegalStateException, NumberFormatException 201 { 202 var retValue = defaultValue; 203 final var value = get( name ); 204 if( value.isPresent() ) 205 { 206 final var number = value.get().asNumber(); 207 retValue = number.getDouble(); 208 } 209 210 //---* Done *---------------------------------------------------------- 211 return retValue; 212 } // getDouble() 213 214 /** 215 * <p>{@summary Convenience method that returns the value with the 216 * specified name as a {@code float}.}</p> 217 * 218 * @param name The name of the member whose value is to be returned. 219 * @param defaultValue The value to be returned if the requested 220 * member is missing. 221 * @return The value of the member with the specified name, or the given 222 * default value if this object does not contain a member with that 223 * name. 224 * @throws IllegalStateException The member exists, but it is not a 225 * number. 226 * @throws NumberFormatException The member exists, and it is a number, 227 * but cannot be parsed to a valid {@code float}. 228 */ 229 public default float getFloat( final String name, final float defaultValue ) throws IllegalStateException, NumberFormatException 230 { 231 var retValue = defaultValue; 232 final var value = get( name ); 233 if( value.isPresent() ) 234 { 235 final var number = value.get().asNumber(); 236 retValue = number.getFloat(); 237 } 238 239 //---* Done *---------------------------------------------------------- 240 return retValue; 241 } // getFloat() 242 243 /** 244 * <p>{@summary Convenience method that returns the value with the 245 * specified name as a {@code int}.}</p> 246 * 247 * @param name The name of the member whose value is to be returned. 248 * @param defaultValue The value to be returned if the requested 249 * member is missing; can be {@null}. 250 * @return The value of the member with the specified name, or the given 251 * default value if this object does not contain a member with that 252 * name. 253 * @throws IllegalStateException The member exists, but it is not a 254 * number. 255 * @throws NumberFormatException The member exists, and it is a number, 256 * but cannot be parsed to a valid {@code int}. 257 */ 258 public default int getInt( final String name, final int defaultValue ) throws IllegalStateException, NumberFormatException 259 { 260 var retValue = defaultValue; 261 final var value = get( name ); 262 if( value.isPresent() ) 263 { 264 final var number = value.get().asNumber(); 265 retValue = number.getInt(); 266 } 267 268 //---* Done *---------------------------------------------------------- 269 return retValue; 270 } // getInt() 271 272 /** 273 * <p>{@summary Convenience method that returns the value with the 274 * specified name as a {@code long}.}</p> 275 * 276 * @param name The name of the member whose value is to be returned. 277 * @param defaultValue The value to be returned if the requested 278 * member is missing. 279 * @return The value of the member with the specified name, or the given 280 * default value if this object does not contain a member with that 281 * name. 282 * @throws IllegalStateException The member exists, but it is not a 283 * number. 284 * @throws NumberFormatException The member exists, and it is a number, 285 * but cannot be parsed to a valid {@code long}. 286 */ 287 public default long getLong( final String name, final long defaultValue ) throws IllegalStateException, NumberFormatException 288 { 289 var retValue = defaultValue; 290 final var value = get( name ); 291 if( value.isPresent() ) 292 { 293 final var number = value.get().asNumber(); 294 retValue = number.getLong(); 295 } 296 297 //---* Done *---------------------------------------------------------- 298 return retValue; 299 } // getLong() 300 301 /** 302 * <p>{@summary Convenience method that returns the value with the 303 * specified name as a {@code JSONObject}.}</p> 304 * 305 * @param name The name of the member whose value is to be returned. 306 * @param defaultValue The value to be returned if the requested 307 * member is missing; can be {@null}. 308 * @return The value of the member with the specified name, or the given 309 * default value if this object does not contain a member with that 310 * name. 311 * @throws IllegalStateException The member exists, but it is not a 312 * JSON Object. 313 */ 314 public default JSONObject getObject( final String name, final JSONObject defaultValue ) throws IllegalStateException 315 { 316 final var retValue = get( name ).map( JSONValue::asObject ).orElse( defaultValue ); 317 318 //---* Done *---------------------------------------------------------- 319 return retValue; 320 } // getObject() 321 322 /** 323 * <p>{@summary Convenience method that returns the value with the 324 * specified name as a 325 * {@link String}.}</p> 326 * 327 * @param name The name of the member whose value is to be returned. 328 * @param defaultValue The value to be returned if the requested 329 * member is missing; can be {@null}. 330 * @return The value of the member with the specified name, or the given 331 * default value if this object does not contain a member with that 332 * name. 333 * @throws IllegalStateException The member exists, but it is not a 334 * {@code String}. 335 */ 336 public default String getString( final String name, final String defaultValue ) throws IllegalStateException 337 { 338 var retValue = defaultValue; 339 final var value = get( name ); 340 if( value.isPresent() ) 341 { 342 final var jsonString = value.get().asString(); 343 retValue = jsonString.getString(); 344 } 345 346 //---* Done *---------------------------------------------------------- 347 return retValue; 348 } // getString() 349 350 /** 351 * Checks whether this object has members. 352 * 353 * @return {@true} if the object does not have any members, 354 * {@false} otherwise. 355 */ 356 public boolean isEmpty(); 357 358 /** 359 * <p>{@summary Copies all members of the specified object into this 360 * object.} When the specified object contains members with names that 361 * also exist in this object, the existing values in this object will be 362 * replaced by the corresponding values in the specified object.</p> 363 * 364 * @param object The object to merge. 365 * @return This object itself, to enable method chaining. 366 */ 367 public JSONObject merge( final JSONObject object ); 368 369 /** 370 * <p>{@summary Returns the names of the members of this object in 371 * document order.}</p> 372 * <p>The return value is backed by this object and will reflect 373 * subsequent changes. It cannot be used to modify this object. Attempts 374 * to modify the returned data structure will result in an exception.</p> 375 * 376 * @return The names. 377 */ 378 public SequencedCollection<String> names(); 379 380 /** 381 * <p>{@summary Removes a member with the specified name from this 382 * object.} If this object does not contain a member with the specified 383 * name, the object is not modified.</p> 384 * 385 * @param name The name of the member to remove. 386 * @return This object itself, to enable method chaining. 387 */ 388 public JSONObject remove( final String name ); 389 390 /** 391 * <p>{@summary Sets the value of the member with the specified name to 392 * the JSON representation of the specified 393 * {@link BigDecimal} 394 * value.}</p> 395 * <p>If this object does not contain a member with this name, a new 396 * member is added at the end of the object.</p> 397 * 398 * @param name The name of the member to replace or to add. 399 * @param value The value to set to the member. 400 * @return This object itself, to enable method chaining. 401 */ 402 public JSONObject set( final String name, final BigDecimal value ); 403 404 /** 405 * <p>{@summary Sets the value of the member with the specified name to 406 * the JSON representation of the specified 407 * {@link BigInteger} 408 * value.}</p> 409 * <p>If this object does not contain a member with this name, a new 410 * member is added at the end of the object.</p> 411 * 412 * @param name The name of the member to replace or to add. 413 * @param value The value to set to the member. 414 * @return This object itself, to enable method chaining. 415 */ 416 public JSONObject set( final String name, final BigInteger value ); 417 418 /** 419 * <p>{@summary Sets the value of the member with the specified name to 420 * the JSON representation of the specified {@code boolean} value.}</p> 421 * <p>If this object does not contain a member with this name, a new 422 * member is added at the end of the object.</p> 423 * 424 * @param name The name of the member to replace or to add. 425 * @param value The value to set to the member. 426 * @return This object itself, to enable method chaining. 427 */ 428 public default JSONObject set( final String name, final boolean value ) 429 { 430 return set( name, value ? TRUE : FALSE ); 431 } // set() 432 433 /** 434 * <p>{@summary Sets the value of the member with the specified name to 435 * the JSON representation of the specified 436 * {@link DimensionedValue } 437 * value.}</p> 438 * <p>If this object does not contain a member with this name, a new 439 * member is added at the end of the object.</p> 440 * 441 * @param <T> The type of the dimension for the value. 442 * @param name The name of the member to replace or to add. 443 * @param value The value. 444 * @param targetUnit The dimension for the output. 445 * @return This object itself, to enable method chaining. 446 * 447 * @see JSONBuilder#valueOf(DimensionedValue, Dimension) 448 */ 449 public <T extends Dimension> JSONObject set( final String name, final DimensionedValue<T> value, final T targetUnit ); 450 451 /** 452 * <p>{@summary Sets the value of the member with the specified name to 453 * the JSON representation of the specified {@code double} value.}</p> 454 * <p>If this object does not contain a member with this name, a new 455 * member is added at the end of the object.</p> 456 * 457 * @param name The name of the member to replace or to add. 458 * @param value The value to set to the member. 459 * @return This object itself, to enable method chaining. 460 */ 461 public JSONObject set( final String name, final double value ); 462 463 /** 464 * <p>{@summary Sets the value of the member with the specified name to 465 * the JSON representation of the specified 466 * {@link Double} 467 * value.}</p> 468 * <p>If this object does not contain a member with this name, a new 469 * member is added at the end of the object.</p> 470 * 471 * @param name The name of the member to replace or to add. 472 * @param value The value to set to the member. 473 * @return This object itself, to enable method chaining. 474 */ 475 public JSONObject set( final String name, final Double value ); 476 477 /** 478 * <p>{@summary Sets the value of the member with the specified name to 479 * the JSON representation of the specified {@code float} value.}</p> 480 * <p>If this object does not contain a member with this name, a new 481 * member is added at the end of the object.</p> 482 * 483 * @param name The name of the member to replace or to add. 484 * @param value The value to set to the member. 485 * @return This object itself, to enable method chaining. 486 */ 487 public JSONObject set( final String name, final float value ); 488 489 /** 490 * <p>{@summary Sets the value of the member with the specified name to 491 * the JSON representation of the specified 492 * {@link Float} 493 * value.}</p> 494 * <p>If this object does not contain a member with this name, a new 495 * member is added at the end of the object.</p> 496 * 497 * @param name The name of the member to replace or to add. 498 * @param value The value to set to the member. 499 * @return This object itself, to enable method chaining. 500 */ 501 public JSONObject set( final String name, final Float value ); 502 503 /** 504 * <p>{@summary Sets the value of the member with the specified name to 505 * the JSON representation of the specified {@code int} value.}</p> 506 * <p>If this object does not contain a member with this name, a new 507 * member is added at the end of the object.</p> 508 * 509 * @param name The name of the member to replace or to add. 510 * @param value The value to set to the member. 511 * @return This object itself, to enable method chaining. 512 */ 513 public JSONObject set( final String name, final int value ); 514 515 /** 516 * <p>{@summary Sets the value of the member with the specified name to 517 * the JSON representation of the specified 518 * {@link Integer} 519 * value.}</p> 520 * <p>If this object does not contain a member with this name, a new 521 * member is added at the end of the object.</p> 522 * 523 * @param name The name of the member to replace or to add. 524 * @param value The value to set to the member. 525 * @return This object itself, to enable method chaining. 526 */ 527 public JSONObject set( final String name, final Integer value ); 528 529 /** 530 * <p>{@summary Sets the value of the member with the specified name to 531 * the specified 532 * {@link JSONValue} 533 * value.}</p> 534 * <p>If this object does not contain a member with this name, a new 535 * member is added at the end of the object.</p> 536 * 537 * @param name The name of the member to replace or to add. 538 * @param value The value to set to the member. 539 * @return This object itself, to enable method chaining. 540 */ 541 public JSONObject set( final String name, final JSONValue value ); 542 543 /** 544 * <p>{@summary Sets the value of the member with the specified name to 545 * the JSON representation of the specified {@code long} value.}</p> 546 * <p>If this object does not contain a member with this name, a new 547 * member is added at the end of the object.</p> 548 * 549 * @param name The name of the member to replace or to add. 550 * @param value The value to set to the member. 551 * @return This object itself, to enable method chaining. 552 */ 553 public JSONObject set( final String name, final long value ); 554 555 /** 556 * <p>{@summary Sets the value of the member with the specified name to 557 * the JSON representation of the specified 558 * {@link Long} 559 * value.}</p> 560 * <p>If this object does not contain a member with this name, a new 561 * member is added at the end of the object.</p> 562 * 563 * @param name The name of the member to replace or to add. 564 * @param value The value to set to the member. 565 * @return This object itself, to enable method chaining. 566 */ 567 public JSONObject set( final String name, final Long value ); 568 569 /** 570 * <p>{@summary Sets the value of the member with the specified name to 571 * the JSON representation of the specified 572 * {@link String} 573 * value.}</p> 574 * <p>If this object does not contain a member with this name, a new 575 * member is added at the end of the object.</p> 576 * 577 * @param name The name of the member to replace or to add. 578 * @param value The value to set to the member. 579 * @return This object itself, to enable method chaining. 580 */ 581 public JSONObject set( final String name, final String value ); 582 583 /** 584 * <p>{@summary Sets a new empty instance of 585 * {@link JSONArray} 586 * to this object and returns that.}</p> 587 * 588 * @param name The name of the member. 589 * @return The freshly created {@code JSONArray}. 590 */ 591 public JSONArray setArray( final String name ); 592 593 /** 594 * <p>{@summary Sets a new empty instance of {@code JSONObject} to this 595 * object and returns that.}</p> 596 * 597 * @param name The name of the member. 598 * @return The freshly created {@code JSONObject}. 599 */ 600 public JSONObject setObject( final String name ); 601 602 /** 603 * <p>{@summary Returns the number of members (name/value pairs) in this 604 * object.}</p> 605 * 606 * @return The number of members in this object. 607 */ 608 public int size(); 609} 610// interface JSONObject 611 612/* 613 * End of File 614 */