001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 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, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.marshall.parser; 018 019import static org.apache.juneau.commons.utils.CollectionUtils.*; 020import static org.apache.juneau.commons.utils.Shorts.*; 021import static org.apache.juneau.commons.utils.StringUtils.*; 022import static org.apache.juneau.commons.utils.SystemUtils.*; 023 024import java.io.*; 025import java.lang.reflect.*; 026import java.nio.charset.*; 027import java.util.*; 028 029import org.apache.juneau.commons.collections.*; 030import org.apache.juneau.commons.http.*; 031import org.apache.juneau.commons.reflect.*; 032import org.apache.juneau.marshall.*; 033import org.apache.juneau.marshall.collections.*; 034import org.apache.juneau.marshall.html.*; 035import org.apache.juneau.marshall.json.*; 036import org.apache.juneau.marshall.msgpack.*; 037import org.apache.juneau.marshall.objecttools.*; 038import org.apache.juneau.marshall.stream.*; 039import org.apache.juneau.marshall.swap.spi.*; 040import org.apache.juneau.marshall.uon.*; 041import org.apache.juneau.marshall.xml.*; 042 043/** 044 * Parent class for all Juneau parsers. 045 * 046 * <h5 class='topic'>Valid data conversions</h5> 047 * <p> 048 * Parsers can parse any parsable POJO types, as specified in the <a class="doclink" href="https://juneau.apache.org/docs/topics/PojoCategories">POJO Categories</a>. 049 * 050 * <p> 051 * Some examples of conversions are shown below... 052 * </p> 053 * <table class='styled'> 054 * <tr> 055 * <th>Data type</th> 056 * <th>Class type</th> 057 * <th>JSON example</th> 058 * <th>XML example</th> 059 * <th>Class examples</th> 060 * </tr> 061 * <tr> 062 * <td>object</td> 063 * <td>Maps, Java beans</td> 064 * <td class='code'>{name:<js>'John Smith'</js>,age:21}</td> 065 * <td class='code'><xt><object> 066 * <name</xt> <xa>type</xa>=<xs>'string'</xs><xt>></xt>John Smith<xt></name> 067 * <age</xt> <xa>type</xa>=<xs>'number'</xs><xt>></xt>21<xt></age> 068 * </object></xt></td> 069 * <td class='code'>HashMap, TreeMap<String,Integer></td> 070 * </tr> 071 * <tr> 072 * <td>array</td> 073 * <td>Collections, Java arrays</td> 074 * <td class='code'>[1,2,3]</td> 075 * <td class='code'><xt><array> 076 * <number></xt>1<xt></number> 077 * <number></xt>2<xt></number> 078 * <number></xt>3<xt></number> 079 * </array></xt></td> 080 * <td class='code'>List<Integer>, <jk>int</jk>[], Float[], Set<Person></td> 081 * </tr> 082 * <tr> 083 * <td>number</td> 084 * <td>Numbers</td> 085 * <td class='code'>123</td> 086 * <td class='code'><xt><number></xt>123<xt></number></xt></td> 087 * <td class='code'>Integer, Long, Float, <jk>int</jk></td> 088 * </tr> 089 * <tr> 090 * <td>boolean</td> 091 * <td>Booleans</td> 092 * <td class='code'><jk>true</jk></td> 093 * <td class='code'><xt><boolean></xt>true<xt></boolean></xt></td> 094 * <td class='code'>Boolean</td> 095 * </tr> 096 * <tr> 097 * <td>string</td> 098 * <td>CharSequences</td> 099 * <td class='code'><js>'foobar'</js></td> 100 * <td class='code'><xt><string></xt>foobar<xt></string></xt></td> 101 * <td class='code'>String, StringBuilder</td> 102 * </tr> 103 * </table> 104 * 105 * <p> 106 * In addition, any class types with {@link ObjectSwap ObjectSwaps} associated with them on the registered 107 * bean context can also be passed in. 108 * 109 * <p> 110 * For example, if a {@link CalendarFormat}-driven swap is used to generalize {@code Calendar} objects to {@code String} 111 * objects. 112 * When registered with this parser, you can construct {@code Calendar} objects from {@code Strings} using the 113 * following syntax... 114 * <p class='bjava'> 115 * Calendar <jv>calendar</jv> = <jv>parser</jv>.read(<js>"'Sun Mar 03 04:05:06 EST 2001'"</js>, GregorianCalendar.<jk>class</jk>); 116 * </p> 117 * 118 * <p> 119 * If <code>Object.<jk>class</jk></code> is specified as the target type, then the parser automatically determines the 120 * data types and generates the following object types... 121 * <table class='styled'> 122 * <tr><th>JSON type</th><th>Class type</th></tr> 123 * <tr><td>object</td><td>{@link JsonMap}</td></tr> 124 * <tr><td>array</td><td>{@link JsonList}</td></tr> 125 * <tr><td>number</td><td>{@link Number}<br>(depending on length and format, could be {@link Integer}, 126 * {@link Double}, {@link Float}, etc...)</td></tr> 127 * <tr><td>boolean</td><td>{@link Boolean}</td></tr> 128 * <tr><td>string</td><td>{@link String}</td></tr> 129 * </table> 130 * 131 * <h5 class='section'>Notes:</h5><ul> 132 * <li class='note'>This class is thread safe and reusable. 133 * </ul> 134 * 135 * <h5 class='section'>See Also:</h5><ul> 136 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SerializersAndParsers">Serializers and Parsers</a> 137 138 * </ul> 139 */ 140@SuppressWarnings({ 141 "java:S1192", // Duplicated literals (argument/property names) read more clearly inline than as constants 142 "rawtypes" // createParserBuilder() returns the raw Builder because the builder subtype is only known reflectively. 143}) 144public class Parser extends MarshallingContextable { 145 146 /** 147 * Builder class. 148 */ 149 @SuppressWarnings({ 150 "java:S119" // 'SELF' (CRTP self-type) is intentional and clearer than a single-letter name. 151 }) 152 public abstract static class Builder<SELF extends Builder<SELF>> extends MarshallingContextable.Builder<SELF> { 153 154 private boolean autoCloseStreams; 155 private boolean trimStrings; 156 private boolean unbuffered; 157 private Class<? extends ParserListener> listener; 158 private int debugOutputLines; 159 private String consumes; 160 private Nulls nulls; 161 162 /** 163 * Constructor, default settings. 164 */ 165 protected Builder() { 166 autoCloseStreams = env("Parser.autoCloseStreams", false); 167 trimStrings = env("Parser.trimStrings", false); 168 unbuffered = env("Parser.unbuffered", false); 169 debugOutputLines = env("Parser.debugOutputLines", 5); 170 listener = null; 171 consumes = null; 172 nulls = Nulls.NOT_SET; 173 } 174 175 /** 176 * Copy constructor. 177 * 178 * @param copyFrom The builder to copy from. 179 * <br>Cannot be <jk>null</jk>. 180 */ 181 protected Builder(Builder<?> copyFrom) { 182 super(copyFrom); 183 autoCloseStreams = copyFrom.autoCloseStreams; 184 trimStrings = copyFrom.trimStrings; 185 unbuffered = copyFrom.unbuffered; 186 debugOutputLines = copyFrom.debugOutputLines; 187 listener = copyFrom.listener; 188 consumes = copyFrom.consumes; 189 nulls = copyFrom.nulls; 190 } 191 192 /** 193 * Copy constructor. 194 * 195 * @param copyFrom The bean to copy from. 196 * <br>Cannot be <jk>null</jk>. 197 */ 198 protected Builder(Parser copyFrom) { 199 super(copyFrom); 200 autoCloseStreams = copyFrom.autoCloseStreams; 201 trimStrings = copyFrom.trimStrings; 202 unbuffered = copyFrom.unbuffered; 203 debugOutputLines = copyFrom.debugOutputLines; 204 listener = copyFrom.listener; 205 consumes = copyFrom.consumes; 206 nulls = copyFrom.nulls; 207 } 208 209 /** 210 * Auto-close streams. 211 * 212 * <p> 213 * When enabled, <l>InputStreams</l> and <l>Readers</l> passed into parsers will be closed 214 * after parsing is complete. 215 * 216 * <h5 class='section'>Example:</h5> 217 * <p class='bjava'> 218 * <jc>// Create a parser using strict mode.</jc> 219 * ReaderParser <jv>parser</jv> = JsonParser 220 * .<jsm>create</jsm>() 221 * .autoCloseStreams() 222 * .build(); 223 * 224 * Reader <jv>myReader</jv> = <jk>new</jk> FileReader(<js>"/tmp/myfile.json"</js>); 225 * MyBean <jv>myBean</jv> = <jv>parser</jv>.read(<jv>myReader</jv>, MyBean.<jk>class</jk>); 226 * 227 * <jsm>assertTrue</jsm>(<jv>myReader</jv>.isClosed()); 228 * </p> 229 * 230 * @return This object. 231 */ 232 public SELF autoCloseStreams() { 233 return autoCloseStreams(true); 234 } 235 236 /** 237 * Same as {@link #autoCloseStreams()} but allows you to explicitly specify the value. 238 * 239 * @param value The value for this setting. 240 * @return This object. 241 */ 242 public SELF autoCloseStreams(boolean value) { 243 autoCloseStreams = value; 244 return self(); 245 } 246 247 @Override /* Overridden from Context.Builder<?> */ 248 public Parser build() { 249 return build(Parser.class); 250 } 251 252 /** 253 * Specifies the media type that this parser consumes. 254 * 255 * <p> 256 * <b>Token streams:</b> this setting is not honored by {@link TokenReadable#readTokens(Object) readTokens} 257 * — media-type metadata is informational, not behavioral. 258 * 259 * @param value The value for this setting. 260 * <br>Can be <jk>null</jk> (treated as empty string, no media types will be specified). 261 * @return This object. 262 */ 263 public SELF consumes(String value) { 264 consumes = value; 265 return self(); 266 } 267 268 @Override /* Overridden from Context.Builder<?> */ 269 public abstract SELF copy(); 270 271 /** 272 * Debug output lines. 273 * 274 * <p> 275 * When parse errors occur, this specifies the number of lines of input before and after the 276 * error location to be printed as part of the exception message. 277 * 278 * <h5 class='section'>Example:</h5> 279 * <p class='bjava'> 280 * <jc>// Create a parser whose exceptions print out 100 lines before and after the parse error location.</jc> 281 * ReaderParser <jv>parser</jv> = JsonParser 282 * .<jsm>create</jsm>() 283 * .debug() <jc>// Enable debug mode to capture Reader contents as strings.</jc> 284 * .debugOuputLines(100) 285 * .build(); 286 * 287 * Reader <jv>myReader</jv> = <jk>new</jk> FileReader(<js>"/tmp/mybadfile.json"</js>); 288 * <jk>try</jk> { 289 * <jv>parser</jv>.read(<jv>myReader</jv>, Object.<jk>class</jk>); 290 * } <jk>catch</jk> (ParseException <jv>e</jv>) { 291 * System.<jsf>err</jsf>.println(<jv>e</jv>.getMessage()); <jc>// Will display 200 lines of the output.</jc> 292 * } 293 * </p> 294 * 295 * <p> 296 * <b>Token streams:</b> this setting is not honored by {@link TokenReadable#readTokens(Object) readTokens} 297 * — it controls error-message formatting on the POJO databind path; the cursor uses its own 298 * exception text. 299 * 300 * @param value 301 * The new value for this property. 302 * <br>The default value is <c>5</c>. 303 * @return This object. 304 */ 305 public SELF debugOutputLines(int value) { 306 debugOutputLines = value; 307 return self(); 308 } 309 310 /** 311 * Returns the current value for the 'consumes' property. 312 * 313 * @return The current value for the 'consumes' property, or <jk>null</jk> if not specified. 314 */ 315 public String getConsumes() { return consumes; } 316 317 @Override /* Overridden from Context.Builder<?> */ 318 public HashKey hashKey() { 319 // @formatter:off 320 return HashKey.of( 321 super.hashKey(), 322 autoCloseStreams, 323 trimStrings, 324 unbuffered, 325 debugOutputLines, 326 listener, 327 consumes, 328 nulls 329 ); 330 // @formatter:on 331 } 332 333 /** 334 * Parser listener. 335 * 336 * <p> 337 * Class used to listen for errors and warnings that occur during parsing. 338 * 339 * <h5 class='section'>Example:</h5> 340 * <p class='bjava'> 341 * <jc>// Define our parser listener.</jc> 342 * <jc>// Simply captures all unknown bean property events.</jc> 343 * <jk>public class</jk> MyParserListener <jk>extends</jk> ParserListener { 344 * 345 * <jc>// A simple property to store our events.</jc> 346 * <jk>public</jk> List<String> <jf>events</jf> = <jk>new</jk> LinkedList<>(); 347 * 348 * <ja>@Override</ja> 349 * <jk>public</jk> <T> <jk>void</jk> onUnknownBeanProperty(ParserSession <jv>session</jv>, String <jv>propertyName</jv>, Class<T> <jv>beanClass</jv>, T <jv>bean</jv>) { 350 * Position <jv>position</jv> = <jv>parser</jv>.getPosition(); 351 * <jf>events</jf>.add(<jv>propertyName</jv> + <js>","</js> + <jv>position</jv>.getLine() + <js>","</js> + <jv>position</jv>.getColumn()); 352 * } 353 * } 354 * 355 * <jc>// Create a parser using our listener.</jc> 356 * ReaderParser <jv>parser</jv> = JsonParser 357 * .<jsm>create</jsm>() 358 * .listener(MyParserListener.<jk>class</jk>) 359 * .build(); 360 * 361 * <jc>// Create a session object.</jc> 362 * <jc>// Needed because listeners are created per-session.</jc> 363 * <jk>try</jk> (ReaderParserSession <jv>session</jv> = <jv>parser</jv>.createSession()) { 364 * 365 * <jc>// Parse some JSON object.</jc> 366 * MyBean <jv>myBean</jv> = <jv>session</jv>.read(<js>"{...}"</js>, MyBean.<jk>class</jk>); 367 * 368 * <jc>// Get the listener.</jc> 369 * MyParserListener <jv>listener</jv> = <jv>session</jv>.getListener(MyParserListener.<jk>class</jk>); 370 * 371 * <jc>// Dump the results to the console.</jc> 372 * Json5.<jsf>DEFAULT</jsf>.println(<jv>listener</jv>.<jf>events</jf>); 373 * } 374 * </p> 375 * 376 * <p> 377 * <b>Token streams:</b> this setting is not honored by {@link TokenReadable#readTokens(Object) readTokens} 378 * — listeners are POJO-level observers with no token-layer analog. 379 * 380 * @param value The new value for this property. 381 * <br>Can be <jk>null</jk> (no listener will be used, listener methods will not be called). 382 * @return This object. 383 */ 384 public SELF listener(Class<? extends ParserListener> value) { 385 listener = value; 386 return self(); 387 } 388 389 /** 390 * Sets the default per-property null-coercion policy applied during parsing. 391 * 392 * <p> 393 * Juneau's analog of Jackson's 394 * <c>ObjectMapper.setDefaultSetterInfo(JsonSetter.Value.forValueNulls(...))</c>. 395 * Applied as the fallback when no per-property 396 * {@link MarshalledProp#nulls() @MarshalledProp(nulls=…)} is configured. 397 * 398 * <h5 class='section'>Example:</h5> 399 * <p class='bjava'> 400 * <jc>// Substitute the empty value for any property whose wire value is null.</jc> 401 * ReaderParser <jv>parser</jv> = JsonParser 402 * .<jsm>create</jsm>() 403 * .nulls(Nulls.<jsf>EMPTY</jsf>) 404 * .build(); 405 * </p> 406 * 407 * @param value The new value for this property. 408 * <br>{@code null} or {@link Nulls#NOT_SET} disables the default (each property falls back to 409 * {@link Nulls#LEAVE}). 410 * @return This object. 411 * @since 10.0.0 412 */ 413 public SELF nulls(Nulls value) { 414 nulls = value == null ? Nulls.NOT_SET : value; 415 return self(); 416 } 417 418 /** 419 * Returns the current context-level {@link Nulls} default configured on this builder. 420 * 421 * @return The current value (never <jk>null</jk>; {@link Nulls#NOT_SET} when unconfigured). 422 * @since 10.0.0 423 */ 424 public Nulls getNulls() { return nulls == null ? Nulls.NOT_SET : nulls; } 425 426 /** 427 * Trim parsed strings. 428 * 429 * <p> 430 * When enabled, string values will be trimmed of whitespace using {@link String#trim()} before being added to 431 * the POJO. 432 * 433 * <h5 class='section'>Example:</h5> 434 * <p class='bjava'> 435 * <jc>// Create a parser with trim-strings enabled.</jc> 436 * ReaderParser <jv>parser</jv> = JsonParser 437 * .<jsm>create</jsm>() 438 * .trimStrings() 439 * .build(); 440 * 441 * <jc>// Use it.</jc> 442 * String <jv>json</jv> = <js>"{' foo ':' bar '}"</js>; 443 * Map<String,String> <jv>myMap</jv> = <jv>parser</jv>.read(<jv>json</jv>, HashMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>); 444 * 445 * <jc>// Make sure strings are parsed.</jc> 446 * <jsm>assertEquals</jsm>(<js>"bar"</js>, <jv>myMap</jv>.get(<js>"foo"</js>)); 447 * </p> 448 * 449 * @return This object. 450 */ 451 public SELF trimStrings() { 452 return trimStrings(true); 453 } 454 455 /** 456 * Same as {@link #trimStrings()} but allows you to explicitly specify the value. 457 * 458 * @param value The value for this setting. 459 * @return This object. 460 */ 461 public SELF trimStrings(boolean value) { 462 trimStrings = value; 463 return self(); 464 } 465 466 /** 467 * Unbuffered. 468 * 469 * <p> 470 * When enabled, don't use internal buffering during parsing. 471 * 472 * <p> 473 * This is useful in cases when you want to parse the same input stream or reader multiple times 474 * because it may contain multiple independent POJOs to parse. 475 * <br>Buffering would cause the parser to read past the current POJO in the stream. 476 * 477 * <h5 class='section'>Example:</h5> 478 * <p class='bjava'> 479 * <jc>// Create a parser using strict mode.</jc> 480 * ReaderParser <jv>parser</jv> = JsonParser. 481 * .<jsm>create</jsm>() 482 * .unbuffered(<jk>true</jk>) 483 * .build(); 484 * 485 * <jc>// If you're calling parse on the same input multiple times, use a session instead of the parser directly.</jc> 486 * <jc>// It's more efficient because we don't need to recalc the session settings again. </jc> 487 * ReaderParserSession <jv>session</jv> = <jv>parser</jv>.createSession(); 488 * 489 * <jc>// Read input with multiple POJOs</jc> 490 * Reader <jv>json</jv> = <jk>new</jk> StringReader(<js>"{foo:'bar'}{foo:'baz'}"</js>); 491 * MyBean <jv>myBean1</jv> = <jv>session</jv>.read(<jv>json</jv>, MyBean.<jk>class</jk>); 492 * MyBean <jv>myBean2</jv> = <jv>session</jv>.read(<jv>json</jv>, MyBean.<jk>class</jk>); 493 * </p> 494 * 495 * <h5 class='section'>Notes:</h5><ul> 496 * <li class='note'> 497 * This only allows for multi-input streams for the following parsers: 498 * <ul> 499 * <li class='jc'>{@link JsonParser} 500 * <li class='jc'>{@link UonParser} 501 * </ul> 502 * It has no effect on the following parsers: 503 * <ul> 504 * <li class='jc'>{@link MsgPackParser} - It already doesn't use buffering. 505 * <li class='jc'>{@link XmlParser}, {@link HtmlParser} - These use StAX which doesn't allow for more than one root element anyway. 506 * <li>RDF parsers - These read everything into an internal model before any parsing begins. 507 * </ul> 508 * </ul> 509 * 510 * @return This object. 511 */ 512 public SELF unbuffered() { 513 return unbuffered(true); 514 } 515 516 /** 517 * Same as {@link #unbuffered()} but allows you to explicitly specify the value. 518 * 519 * @param value The value for this setting. 520 * @return This object. 521 */ 522 public SELF unbuffered(boolean value) { 523 unbuffered = value; 524 return self(); 525 } 526 527 528 } 529 530 /** 531 * Concrete default builder leaf for the non-subclassed {@link Parser#create()} / {@link Parser#copy()} path. 532 */ 533 public static final class DefaultBuilder extends Builder<DefaultBuilder> { 534 535 DefaultBuilder() {} 536 537 DefaultBuilder(Parser copyFrom) { 538 super(copyFrom); 539 } 540 541 DefaultBuilder(Builder<?> copyFrom) { 542 super(copyFrom); 543 } 544 545 @Override /* Overridden from Context.Builder<?> */ 546 public DefaultBuilder copy() { 547 return new DefaultBuilder(this); 548 } 549 } 550 551 /** 552 * Represents no Parser. 553 */ 554 public abstract static class Null extends Parser { 555 @SuppressWarnings({ 556 "java:S1186" // Constructor required by Parser parent class, even though Null is abstract and never instantiated directly 557 }) 558 private Null(Builder<?> builder) { 559 super(builder); 560 } 561 } 562 563 /** 564 * Creates a new builder for this object. 565 * 566 * @return A new builder. 567 */ 568 @SuppressWarnings({ 569 "java:S1452" // Self-typed builder: Builder<?> is the only non-raw, leaf-free return; chaining + build() unaffected. 570 }) 571 public static Builder<?> create() { 572 return new DefaultBuilder(); 573 } 574 575 /** 576 * Instantiates a builder of the specified parser class. 577 * 578 * <p> 579 * Looks for a public static method called <c>create</c> that returns an object that can be passed into a public 580 * or protected constructor of the class. 581 * 582 * @param c The builder to create. 583 * <br>Must not be <jk>null</jk>. 584 * @return A new builder. 585 */ 586 public static Builder createParserBuilder(Class<? extends Parser> c) { 587 return (Builder)Context.createBuilder(c); 588 } 589 590 protected final boolean autoCloseStreams; 591 protected final boolean trimStrings; 592 protected final boolean unbuffered; 593 protected final int debugOutputLines; 594 protected final Class<? extends ParserListener> listener; 595 protected final String consumes; 596 protected final Nulls nulls; 597 private final List<MediaType> consumesArray; 598 599 /** 600 * Constructor. 601 * 602 * @param builder The builder for this object. 603 * <br>Cannot be <jk>null</jk>. 604 */ 605 protected Parser(Builder<?> builder) { 606 super(builder); 607 608 autoCloseStreams = builder.autoCloseStreams; 609 consumes = builder.consumes; 610 debugOutputLines = builder.debugOutputLines; 611 listener = builder.listener; 612 trimStrings = builder.trimStrings; 613 unbuffered = builder.unbuffered; 614 nulls = builder.nulls == null ? Nulls.NOT_SET : builder.nulls; 615 616 String[] consumesParts = splita(nn(consumes) ? consumes : ""); 617 List<MediaType> consumesList = l(); 618 for (var consume : consumesParts) { 619 consumesList.add(MediaType.of(consume)); 620 } 621 this.consumesArray = u(consumesList); 622 } 623 624 /** 625 * Returns <jk>true</jk> if this parser can handle the specified content type. 626 * 627 * @param contentType The content type to test. 628 * <br>Can be <jk>null</jk> (returns <jk>false</jk>). 629 * @return <jk>true</jk> if this parser can handle the specified content type. 630 */ 631 public boolean canHandle(String contentType) { 632 if (nn(contentType)) 633 for (var mt : getMediaTypes()) 634 if (eq(contentType, mt.toString())) 635 return true; 636 return false; 637 } 638 639 @Override /* Overridden from Context */ 640 public Builder<?> copy() { 641 return new DefaultBuilder(this); 642 } 643 644 @Override /* Overridden from Context */ 645 public ParserSession.Builder<?> createSession() { 646 return ParserSession.create(this); 647 } 648 649 /** 650 * Workhorse method. 651 * 652 * <p> 653 * Subclasses are expected to either implement this method or {@link ParserSession#doRead(ParserPipe, ClassMeta)}. 654 * 655 * @param session The current session. 656 * @param pipe Where to get the input from. 657 * @param type 658 * The class type of the object to create. 659 * If <jk>null</jk> or <code>Object.<jk>class</jk></code>, object type is based on what's being parsed. 660 * For example, when parsing JSON text, it may return a <c>String</c>, <c>Number</c>, 661 * <c>JsonMap</c>, etc... 662 * @param <T> The class type of the object to create. 663 * @return The parsed object. 664 * @throws IOException Thrown by underlying stream. 665 * @throws ParseException Malformed input encountered. 666 * @throws ExecutableException Exception occurred on invoked constructor/method/field. 667 */ 668 public <T> T doRead(ParserSession session, ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException { 669 throw uoex(); 670 } 671 672 /** 673 * Returns the media types handled based on the values passed to the <c>consumes</c> constructor parameter. 674 * 675 * @return The list of media types. Never <jk>null</jk>. 676 */ 677 public final List<MediaType> getMediaTypes() { return consumesArray; } 678 679 /** 680 * Returns the first media type handled based on the values passed to the <c>consumes</c> constructor parameter. 681 * 682 * @return The media type, or <jk>null</jk> if no media types are handled by this parser. 683 */ 684 public final MediaType getPrimaryMediaType() { return first(consumesArray).orElse(null); } 685 686 @Override /* Overridden from Context */ 687 public ParserSession getSession() { return createSession().build(); } 688 689 /** 690 * Returns <jk>true</jk> if this parser subclasses from {@link ReaderParser}. 691 * 692 * @return <jk>true</jk> if this parser subclasses from {@link ReaderParser}. 693 */ 694 public boolean isReaderParser() { return true; } 695 696 /** 697 * Same as {@link #read(Object, Type, Type...)} except optimized for a non-parameterized class. 698 * 699 * <p> 700 * This is the preferred parse method for simple types since you don't need to cast the results. 701 * 702 * <h5 class='section'>Examples:</h5> 703 * <p class='bjava'> 704 * ReaderParser <jv>parser</jv> = JsonParser.<jsf>DEFAULT</jsf>; 705 * 706 * <jc>// Parse into a string.</jc> 707 * String <jv>string</jv> = <jv>parser</jv>.read(<jv>json</jv>, String.<jk>class</jk>); 708 * 709 * <jc>// Parse into a bean.</jc> 710 * MyBean <jv>bean</jv> = <jv>parser</jv>.read(<jv>json</jv>, MyBean.<jk>class</jk>); 711 * 712 * <jc>// Parse into a bean array.</jc> 713 * MyBean[] <jv>beanArray</jv> = <jv>parser</jv>.read(<jv>json</jv>, MyBean[].<jk>class</jk>); 714 * 715 * <jc>// Parse into a linked-list of objects.</jc> 716 * List <jv>list</jv> = <jv>parser</jv>.read(<jv>json</jv>, LinkedList.<jk>class</jk>); 717 * 718 * <jc>// Parse into a map of object keys/values.</jc> 719 * Map <jv>map</jv> = <jv>parser</jv>.read(<jv>json</jv>, TreeMap.<jk>class</jk>); 720 * </p> 721 * 722 * @param <T> The class type of the object being created. 723 * @param input 724 * The input. 725 * See {@link #read(Object, Type, Type...)} for details. 726 * @param type The object type to create. 727 * @return The parsed object. 728 * @throws ParseException Malformed input encountered. 729 * @throws IOException Thrown by the underlying stream. 730 */ 731 public final <T> T read(Object input, Class<T> type) throws ParseException, IOException { 732 return getSession().read(input, type); 733 } 734 735 /** 736 * Same as {@link #read(Object, Type, Type...)} except the type has already been converted into a {@link ClassMeta} 737 * object. 738 * 739 * <p> 740 * This is mostly an internal method used by the framework. 741 * 742 * @param <T> The class type of the object being created. 743 * @param input 744 * The input. 745 * See {@link #read(Object, Type, Type...)} for details. 746 * @param type The object type to create. 747 * @return The parsed object. 748 * @throws ParseException Malformed input encountered. 749 * @throws IOException Thrown by the underlying stream. 750 */ 751 public final <T> T read(Object input, ClassMeta<T> type) throws ParseException, IOException { 752 return getSession().read(input, type); 753 } 754 755 /** 756 * Parses input into the specified object type. 757 * 758 * <p> 759 * The type can be a simple type (e.g. beans, strings, numbers) or parameterized type (collections/maps). 760 * 761 * <h5 class='section'>Examples:</h5> 762 * <p class='bjava'> 763 * ReaderParser <jv>parser</jv> = JsonParser.<jsf>DEFAULT</jsf>; 764 * 765 * <jc>// Parse into a linked-list of strings.</jc> 766 * List <jv>list1</jv> = <jv>parser</jv>.read(<jv>json</jv>, LinkedList.<jk>class</jk>, String.<jk>class</jk>); 767 * 768 * <jc>// Parse into a linked-list of beans.</jc> 769 * List <jv>list2</jv> = <jv>parser</jv>.read(<jv>json</jv>, LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>); 770 * 771 * <jc>// Parse into a linked-list of linked-lists of strings.</jc> 772 * List <jv>list3</jv> = <jv>parser</jv>.read(<jv>json</jv>, LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>); 773 * 774 * <jc>// Parse into a map of string keys/values.</jc> 775 * Map <jv>map1</jv> = <jv>parser</jv>.read(<jv>json</jv>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>); 776 * 777 * <jc>// Parse into a map containing string keys and values of lists containing beans.</jc> 778 * Map <jv>map2</jv> = <jv>parser</jv>.read(<jv>json</jv>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>); 779 * </p> 780 * 781 * <p> 782 * <c>Collection</c> classes are assumed to be followed by zero or one objects indicating the element type. 783 * 784 * <p> 785 * <c>Map</c> classes are assumed to be followed by zero or two meta objects indicating the key and value types. 786 * 787 * <p> 788 * The array can be arbitrarily long to indicate arbitrarily complex data structures. 789 * 790 * <h5 class='section'>Notes:</h5><ul> 791 * <li class='note'> 792 * Use the {@link #read(Object, Class)} method instead if you don't need a parameterized map/collection. 793 * </ul> 794 * 795 * @param <T> The class type of the object to create. 796 * @param input 797 * The input. 798 * <br>Character-based parsers can handle the following input class types: 799 * <ul> 800 * <li><jk>null</jk> 801 * <li>{@link Reader} 802 * <li>{@link CharSequence} 803 * <li>{@link InputStream} containing UTF-8 encoded text (or charset defined by 804 * {@link ReaderParser.Builder#streamCharset(Charset)} property value). 805 * <li><code><jk>byte</jk>[]</code> containing UTF-8 encoded text (or charset defined by 806 * {@link ReaderParser.Builder#streamCharset(Charset)} property value). 807 * </ul> 808 * <br>Stream-based parsers can handle the following input class types: 809 * <ul> 810 * <li><jk>null</jk> 811 * <li>{@link InputStream} 812 * <li><code><jk>byte</jk>[]</code> 813 * <li>{@link CharSequence} containing encoded bytes according to the {@link InputStreamParser.Builder#binaryFormat(BinaryFormat)} setting. 814 * </ul> 815 * @param type 816 * The object type to create. 817 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 818 * @param args 819 * The type arguments of the class if it's a collection or map. 820 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 821 * <br>Ignored if the main type is not a map or collection. 822 * @return The parsed object. 823 * @throws ParseException Malformed input encountered. 824 * @throws IOException Thrown by underlying stream. 825 * @see MarshallingSession#getClassMeta(Type,Type...) for argument syntax for maps and collections. 826 */ 827 public final <T> T read(Object input, Type type, Type...args) throws ParseException, IOException { 828 return getSession().read(input, type, args); 829 } 830 831 /** 832 * Same as {@link #read(Object, Class)} but since it's a {@link String} input doesn't throw an {@link IOException}. 833 * 834 * @param <T> The class type of the object being created. 835 * @param input 836 * The input. 837 * See {@link #read(Object, Type, Type...)} for details. 838 * @param type The object type to create. 839 * @return The parsed object. 840 * @throws ParseException Malformed input encountered. 841 */ 842 public final <T> T read(String input, Class<T> type) throws ParseException { 843 return getSession().read(input, type); 844 } 845 846 /** 847 * Same as {@link #read(Object, ClassMeta)} but since it's a {@link String} input doesn't throw an {@link IOException}. 848 * 849 * @param <T> The class type of the object being created. 850 * @param input 851 * The input. 852 * See {@link #read(Object, Type, Type...)} for details. 853 * @param type The object type to create. 854 * @return The parsed object. 855 * @throws ParseException Malformed input encountered. 856 */ 857 public final <T> T read(String input, ClassMeta<T> type) throws ParseException { 858 return getSession().read(input, type); 859 } 860 861 /** 862 * Same as {@link #read(String, ClassMeta)} but creates the parser session with a specific outer object. 863 * 864 * <p> 865 * The outer object is used when instantiating top-level non-static inner classes and when setting 866 * {@link ParentProperty @ParentProperty} fields on parsed beans. 867 * This is important when a parser is used to parse inline content (e.g. JSON5 embedded in a Markdown 868 * table cell) where the parent bean context must be preserved. 869 * 870 * @param <T> The class type of the object being created. 871 * @param input The input string to parse. 872 * @param type The object type to create. 873 * @param outer 874 * The outer object to associate with this parse session. 875 * Used for {@link ParentProperty @ParentProperty} injection and 876 * non-static inner class construction. 877 * Can be <jk>null</jk> (no outer object is associated; <ja>@ParentProperty</ja> injection and non-static inner-class construction are skipped). 878 * @return The parsed object. 879 * @throws ParseException Malformed input encountered. 880 */ 881 public final <T> T readWithOuter(String input, ClassMeta<T> type, Object outer) throws ParseException { 882 return createSession().outer(outer).build().read(input, type); 883 } 884 885 /** 886 * Same as {@link #read(Object, Type, Type...)} but since it's a {@link String} input doesn't throw an {@link IOException}. 887 * 888 * @param <T> The class type of the object being created. 889 * @param input 890 * The input. 891 * See {@link #read(Object, Type, Type...)} for details. 892 * @param type 893 * The object type to create. 894 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 895 * @param args 896 * The type arguments of the class if it's a collection or map. 897 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 898 * <br>Ignored if the main type is not a map or collection. 899 * @return The parsed object. 900 * @throws ParseException Malformed input encountered. 901 */ 902 public final <T> T read(String input, Type type, Type...args) throws ParseException { 903 return getSession().read(input, type, args); 904 } 905 906 /** 907 * Parses the specified array input with each entry in the object defined by the {@code argTypes} 908 * argument. 909 * 910 * <p> 911 * Used for converting arrays (e.g. <js>"[arg1,arg2,...]"</js>) into an {@code Object[]} that can be passed 912 * to the {@code Method.invoke(target, args)} method. 913 * 914 * <p> 915 * Used in the following locations: 916 * <ul class='spaced-list'> 917 * <li> 918 * Used to parse argument strings in the {@link ObjectIntrospector#invokeMethod(Method, Reader)} method. 919 * </ul> 920 * 921 * @param input The input. Subclasses can support different input types. 922 * @param argTypes Specifies the type of objects to create for each entry in the array. 923 * @return An array of parsed objects. 924 * @throws ParseException Malformed input encountered. 925 */ 926 public final Object[] readArgs(Object input, Type[] argTypes) throws ParseException { 927 if (argTypes == null || argTypes.length == 0) 928 return new Object[0]; 929 return getSession().readArgs(input, argTypes); 930 } 931 932 /** 933 * Parses the contents of the specified reader and loads the results into the specified collection. 934 * 935 * <p> 936 * Used in the following locations: 937 * <ul class='spaced-list'> 938 * <li> 939 * The various character-based constructors in {@link JsonList} (e.g. 940 * {@link JsonList#JsonList(CharSequence,Parser)}. 941 * </ul> 942 * 943 * @param <E> The element class type. 944 * @param input The input. See {@link #read(Object, ClassMeta)} for supported input types. 945 * @param c The collection being loaded. 946 * @param elementType The class type of the elements, or <jk>null</jk> to default to whatever is being parsed. 947 * @return The same collection that was passed in to allow this method to be chained. 948 * @throws ParseException Malformed input encountered. 949 * @throws UnsupportedOperationException If not implemented. 950 */ 951 public final <E> Collection<E> readIntoCollection(Object input, Collection<E> c, Type elementType) throws ParseException { 952 return getSession().readIntoCollection(input, c, elementType); 953 } 954 955 /** 956 * Parses the contents of the specified reader and loads the results into the specified map. 957 * 958 * <p> 959 * Reader must contain something that serializes to a map (such as text containing a JSON object). 960 * 961 * <p> 962 * Used in the following locations: 963 * <ul class='spaced-list'> 964 * <li> 965 * The various character-based constructors in {@link JsonMap} (e.g. 966 * {@link JsonMap#JsonMap(CharSequence,Parser)}). 967 * </ul> 968 * 969 * @param <K> The key class type. 970 * @param <V> The value class type. 971 * @param input The input. See {@link #read(Object, ClassMeta)} for supported input types. 972 * @param m The map being loaded. 973 * @param keyType The class type of the keys, or <jk>null</jk> to default to <code>String.<jk>class</jk></code>. 974 * @param valueType The class type of the values, or <jk>null</jk> to default to whatever is being parsed. 975 * @return The same map that was passed in to allow this method to be chained. 976 * @throws ParseException Malformed input encountered. 977 * @throws UnsupportedOperationException If not implemented. 978 */ 979 public final <K,V> Map<K,V> readIntoMap(Object input, Map<K,V> m, Type keyType, Type valueType) throws ParseException { 980 return getSession().readIntoMap(input, m, keyType, valueType); 981 } 982 983 /** 984 * Debug output lines. 985 * 986 * @see Parser.Builder#debugOutputLines(int) 987 * @return 988 * The number of lines of input before and after the error location to be printed as part of the exception message. 989 */ 990 protected final int getDebugOutputLines() { return debugOutputLines; } 991 992 /** 993 * Parser listener. 994 * 995 * @see Parser.Builder#listener(Class) 996 * @return 997 * Class used to listen for errors and warnings that occur during parsing, or <jk>null</jk> if none was configured. 998 */ 999 protected final Class<? extends ParserListener> getListener() { return listener; } 1000 1001 /** 1002 * Auto-close streams. 1003 * 1004 * @see Parser.Builder#autoCloseStreams() 1005 * @return 1006 * <jk>true</jk> if <l>InputStreams</l> and <l>Readers</l> passed into parsers will be closed 1007 * after parsing is complete. 1008 */ 1009 protected final boolean isAutoCloseStreams() { return autoCloseStreams; } 1010 1011 /** 1012 * Trim parsed strings. 1013 * 1014 * @see Parser.Builder#trimStrings() 1015 * @return 1016 * <jk>true</jk> if string values will be trimmed of whitespace using {@link String#trim()} before being added to 1017 * the POJO. 1018 */ 1019 protected final boolean isTrimStrings() { return trimStrings; } 1020 1021 /** 1022 * Returns the context-level {@link Nulls} default consulted at parse-time when no per-property 1023 * {@link MarshalledProp#nulls() @MarshalledProp(nulls=…)} is configured. 1024 * 1025 * @return The current value (never <jk>null</jk>; {@link Nulls#NOT_SET} when unconfigured). 1026 * @see Parser.Builder#nulls(Nulls) 1027 * @since 10.0.0 1028 */ 1029 public final Nulls getNulls() { return nulls; } 1030 1031 /** 1032 * Unbuffered. 1033 * 1034 * @see Parser.Builder#unbuffered() 1035 * @return 1036 * <jk>true</jk> if parsers don't use internal buffering during parsing. 1037 */ 1038 protected final boolean isUnbuffered() { return unbuffered; } 1039 1040 @Override /* Overridden from MarshallingContextable */ 1041 protected FluentMap<String,Object> properties() { 1042 return super.properties() 1043 .a("autoCloseStreams", autoCloseStreams) 1044 .a("debugOutputLines", debugOutputLines) 1045 .a("listener", listener) 1046 .a("nulls", nulls) 1047 .a("trimStrings", trimStrings) 1048 .a("unbuffered", unbuffered); 1049 } 1050}