Codebase list jackson-core / a3fa1de
New upstream version 2.10.0 Mechtilde 4 years ago
109 changed file(s) with 5374 addition(s) and 2035 deletion(s). Raw diff Collapse all Expand all
00 language: java
1 # core streaming still builds on jdk6 and above:
2 # 05-Jan-2018, tatu: Not sure why, but travis build fails on jdk6 so leave it out
3 jdk:
4 - openjdk7
1 # 08-Dec-2018, tatu: While it should be possible to run core streaming on Java 6,
2 # build won't work with anything below Java 8 now
53 - openjdk8
4 - oraclejdk11
65
76 # Below this line is configuration for deploying to the Sonatype OSS repo
87 # http://blog.xeiam.com/2013/05/configure-travis-ci-to-deploy-snapshots.html
1312 branches:
1413 only:
1514 - master
16 - "2.9"
15 - "2.10"
1716
1817 # to make jdk6 work, as per: https://github.com/travis-ci/travis-ci/issues/8199
1918 addons:
0 This copy of Jackson JSON processor annotations is licensed under the
1 Apache (Software) License, version 2.0 ("the License").
2 See the License for details about distribution rights, and the
3 specific rights regarding derivate works.
4
5 You may obtain a copy of the License at:
6
7 http://www.apache.org/licenses/LICENSE-2.0
6969 JsonFactory factory = objectMapper.getFactory();
7070 ```
7171
72 More information can be found from [Streaming API](http://wiki.fasterxml.com/JacksonStreamingApi
73 ) at Jackson Wiki.
74
7572 ## Usage, simple reading
7673
7774 All reading is by using `JsonParser` (or its sub-classes, in case of data formats other than JSON),
105102 * Project [Wiki](../../wiki) has JavaDocs and links to downloadable artifacts
106103 * [Jackson Github Hub](https://github.com/FasterXML/jackson) has links to all official Jackson components
107104 * [Jackson Github Doc](https://github.com/FasterXML/jackson-docs) is the hub for official Jackson documentation
108 * [FasterXML Jackson Project Wiki](http://wiki.fasterxml.com/JacksonHome) has additional documentation (especially for older Jackson versions)
109 * Commercial support (including alternative licensing arrangements) is available by [FasterXML.com](http://fasterxml.com)
110105
11 <modelVersion>4.0.0</modelVersion>
22 <parent>
33 <groupId>com.fasterxml.jackson</groupId>
4 <!-- For 2.9.2 and beyond, new parent pom; extends jackson-bom -->
54 <artifactId>jackson-base</artifactId>
6 <version>2.9.9</version>
5 <version>2.10.0</version>
76 </parent>
87
98 <groupId>com.fasterxml.jackson.core</groupId>
109 <artifactId>jackson-core</artifactId>
1110 <name>Jackson-core</name>
12 <version>2.9.9</version>
11 <version>2.10.0</version>
1312 <packaging>bundle</packaging>
1413 <description>Core Jackson processing abstractions (aka Streaming API), implementation for JSON</description>
1514 <inceptionYear>2008</inceptionYear>
1918 <connection>scm:git:git@github.com:FasterXML/jackson-core.git</connection>
2019 <developerConnection>scm:git:git@github.com:FasterXML/jackson-core.git</developerConnection>
2120 <url>http://github.com/FasterXML/jackson-core</url>
22 <tag>jackson-core-2.9.9</tag>
21 <tag>jackson-core-2.10.0</tag>
2322 </scm>
2423
2524 <properties>
26 <!-- 16-Sep-2016, tatu: Retain Java6/JDK1.6 compatibility for streaming for Jackson 2.x -->
25 <!-- 04-Mar-2019, tatu: Retain Java6/JDK1.6 compatibility for annotations for Jackson 2.x,
26 but use Moditect to get JDK9+ module info support; need newer bundle plugin as well
27 -->
2728 <javac.src.version>1.6</javac.src.version>
2829 <javac.target.version>1.6</javac.target.version>
2930
30 <!-- 04-May-2016, tatu: Bundle-plugin 3.x seems to require Java 7, so to
31 build for Java 6 need to downgrade here to last working 2.x version
32 (2.5.4 had some issues wrt shading)
33 -->
34 <version.plugin.bundle>2.5.3</version.plugin.bundle>
31 <maven.compiler.source>1.6</maven.compiler.source>
32 <maven.compiler.target>1.6</maven.compiler.target>
3533
3634 <osgi.export>com.fasterxml.jackson.core;version=${project.version},
3735 com.fasterxml.jackson.core.*;version=${project.version}
4038 <!-- Generate PackageVersion.java into this directory. -->
4139 <packageVersion.dir>com/fasterxml/jackson/core/json</packageVersion.dir>
4240 <packageVersion.package>${project.groupId}.json</packageVersion.package>
43 <!-- usually above is fine for Automatic Module Name, but not here: -->
44 <jdk.module.name>com.fasterxml.jackson.core</jdk.module.name>
4541 </properties>
4642
4743 <!-- Alas, need to include snapshot reference since otherwise can not find
5854
5955 <build>
6056 <plugins>
57
58 <!-- 26-Aug-2019, tatu: JaCoCo for code coverage -->
59 <plugin>
60 <groupId>org.jacoco</groupId>
61 <artifactId>jacoco-maven-plugin</artifactId>
62 <version>0.8.4</version>
63 <executions>
64 <execution>
65 <goals>
66 <goal>prepare-agent</goal>
67 </goals>
68 </execution>
69 <execution>
70 <id>report</id>
71 <phase>test</phase>
72 <goals>
73 <goal>report</goal>
74 </goals>
75 </execution>
76 </executions>
77 </plugin>
78
6179 <!-- Important: enable enforcer plug-in: -->
6280 <plugin>
6381 <artifactId>maven-enforcer-plugin</artifactId>
95113 <groupId>com.google.code.maven-replacer-plugin</groupId>
96114 <artifactId>replacer</artifactId>
97115 </plugin>
116
117 <!-- 04-Mar-2019, tatu: Add rudimentary JDK9+ module info. To build with JDK 8
118 will have to use `moduleInfoFile` as anything else requires JDK 9+
119 -->
120 <plugin>
121 <groupId>org.moditect</groupId>
122 <artifactId>moditect-maven-plugin</artifactId>
123 </plugin>
98124 </plugins>
99125 </build>
100126
154154 * Suggested #463: Ensure that `skipChildren()` of non-blocking `JsonParser` will throw
155155 exception if not enough input
156156 (2.9.6)
157 * Reported, Contributed test for #563: Async parser does not keep track of Array context properly
158 (2.10.0)
157159
158160 Alexander Eyers-Taylor (aeyerstaylor@github)
159161 * Reported #510: Fix ArrayIndexOutofBoundsException found by LGTM.com
162164 Henrik Gustafsson (gsson@github)
163165 * Reported #516: _inputPtr off-by-one in UTF8StreamJsonParser._parseNumber2()
164166 (2.9.9)
167
168 Alex Rebert (alpire@github)
169 * Reported #540, suggested fix: UTF8StreamJsonParser: fix byte to int conversion for
170 malformed escapes
171 (2.9.10)
172 * Reported #547: `CharsToNameCanonicalizer`: Internal error on `SymbolTable.rehash()` with high
173 number of hash collisions
174 (2.10.0)
175 * Reported #548: ByteQuadsCanonicalizer: ArrayIndexOutOfBoundsException in addName
176 (2.10.0)
177
178 Sam Smith (Oracle Security Researcher)
179 * Reported #540 (concurrently with Alex R, before fix was included)
180 (2.9.10)
181
182 Philippe Marschall (marschall@github)
183 * Requested #480: `SerializableString` value can not directly render to Writer
184 (2.10.0)
185
186 David Nault (dnault@github)
187 * Reported #531: Non-blocking parser reports incorrect locations when fed with
188 non-zero offset
189 (2.10.0)
190
191 Fabien Renaud (fabienrenaud@github)
192 * Reported, contributed fix fir #533: UTF-8 BOM not accounted for in
193 `JsonLocation.getByteOffset()`
194 (2.10.0)
1212 ------------------------------------------------------------------------
1313 === Releases ===
1414 ------------------------------------------------------------------------
15
16 2.10.0 (26-Sep-2019)
17
18 #433: Add Builder pattern for creating configured Stream factories
19 #464: Add "maximum unescaped char" configuration option for `JsonFactory` via builder
20 #467: Create `JsonReadFeature` to move JSON-specific `JsonParser.Feature`s to
21 #479: Improve thread-safety of buffer recycling
22 #480: `SerializableString` value can not directly render to Writer
23 (requested by Philippe M)
24 #481: Create `JsonWriteFeature` to move JSON-specific `JsonGenerator.Feature`s to
25 #484: Implement `UTF8JsonGenerator.writeRawValue(SerializableString)` (and
26 `writeRaw(..)`) more efficiently
27 #495: Create `StreamReadFeature` to move non-json specific `JsonParser.Feature`s to
28 #496: Create `StreamWriteFeature` to take over non-json-specific `JsonGenerator.Feature`s
29 #502: Make `DefaultPrettyPrinter.createInstance()` to fail for sub-classes
30 #506: Add missing type parameter for `TypeReference` in `ObjectCodec`
31 #508: Add new exception type `InputCoercionException` to be used for failed coercions
32 like overflow for `int`
33 #517: Add `JsonGenerator.writeStartObject(Object, int)` (needed by CBOR, maybe Avro)
34 #527: Add simple module-info for JDK9+, using Moditect
35 #533: UTF-8 BOM not accounted for in JsonLocation.getByteOffset()
36 (contributed by Fabien R)
37 #539: Reduce max size of recycled byte[]/char[] blocks by `TextBuffer`, `ByteArrayBuilder`
38 #547: `CharsToNameCanonicalizer`: Internal error on `SymbolTable.rehash()` with high
39 number of hash collisions
40 (reported by Alex R)
41 #548: ByteQuadsCanonicalizer: ArrayIndexOutOfBoundsException in addName
42 (reported by Alex R)
43 #549: Add configurability of "quote character" for JSON factory
44 #561: Misleading exception for unquoted String parsing
45 #563: Async parser does not keep track of Array context properly
46 (reported by Doug R)
47 - Rewrite `JsonGenerator.copyCurrentStructure()` to remove recursion)
48 - Add `missingNode()`, `nullNode()` in `TreeCodec`
49 - Add `JsonParserDelegate.delegate()` methods
50
51 2.9.10 (21-Sep-2019)
52
53 #540: UTF8StreamJsonParser: fix byte to int conversion for malformed escapes
54 (reported by Alex R and Sam S)
55 #556: 'IndexOutOfBoundsException' in UTF8JsonGenerator.writeString(Reader, len)
56 when using a negative length
57 (reported by jacob-alan-ward@github)
1558
1659 2.9.9 (16-May-2019)
1760
8787 private final transient boolean _usesPadding;
8888
8989 /**
90 * Characted used for padding, if any ({@link #PADDING_CHAR_NONE} if not).
90 * Character used for padding, if any ({@link #PADDING_CHAR_NONE} if not).
9191 */
9292 private final transient char _paddingChar;
9393
366366
367367 /**
368368 * Convenience method for converting given byte array as base64 encoded String
369 * using this variant's settings,
370 * optionally enclosed in double-quotes.
369 * using this variant's settings, optionally enclosed in double-quotes.
370 * Linefeeds added, if needed, are expressed as 2-character JSON (and Java source)
371 * escape sequence of backslash + `n`.
371372 *
372373 * @param input Byte array to encode
373374 * @param addQuotes Whether to surround resulting value in double quotes or not
374375 */
375376 public String encode(byte[] input, boolean addQuotes)
376377 {
377 int inputEnd = input.length;
378 StringBuilder sb;
379 {
380 // let's approximate... 33% overhead, ~= 3/8 (0.375)
381 int outputLen = inputEnd + (inputEnd >> 2) + (inputEnd >> 3);
382 sb = new StringBuilder(outputLen);
383 }
378 final int inputEnd = input.length;
379 final StringBuilder sb = new StringBuilder(inputEnd + (inputEnd >> 2) + (inputEnd >> 3));
384380 if (addQuotes) {
385381 sb.append('"');
386382 }
422418 }
423419
424420 /**
421 * Convenience method for converting given byte array as base64 encoded String
422 * using this variant's settings, optionally enclosed in double-quotes.
423 * Linefeed character to use is passed explicitly.
424 *
425 * @param input Byte array to encode
426 * @param addQuotes Whether to surround resulting value in double quotes or not
427 *
428 * @since 2.10
429 */
430 public String encode(byte[] input, boolean addQuotes, String linefeed)
431 {
432 final int inputEnd = input.length;
433 final StringBuilder sb = new StringBuilder(inputEnd + (inputEnd >> 2) + (inputEnd >> 3));
434 if (addQuotes) {
435 sb.append('"');
436 }
437
438 int chunksBeforeLF = getMaxLineLength() >> 2;
439
440 int inputPtr = 0;
441 int safeInputEnd = inputEnd-3;
442
443 while (inputPtr <= safeInputEnd) {
444 int b24 = ((int) input[inputPtr++]) << 8;
445 b24 |= ((int) input[inputPtr++]) & 0xFF;
446 b24 = (b24 << 8) | (((int) input[inputPtr++]) & 0xFF);
447 encodeBase64Chunk(sb, b24);
448 if (--chunksBeforeLF <= 0) {
449 sb.append(linefeed);
450 chunksBeforeLF = getMaxLineLength() >> 2;
451 }
452 }
453 int inputLeft = inputEnd - inputPtr;
454 if (inputLeft > 0) {
455 int b24 = ((int) input[inputPtr++]) << 16;
456 if (inputLeft == 2) {
457 b24 |= (((int) input[inputPtr++]) & 0xFF) << 8;
458 }
459 encodeBase64Partial(sb, b24, inputLeft);
460 }
461
462 if (addQuotes) {
463 sb.append('"');
464 }
465 return sb.toString();
466 }
467
468 /**
425469 * Convenience method for decoding contents of a Base64-encoded String,
426470 * using this variant's settings.
427 *
471 *
428472 * @param input
429 *
430 * @since 2.2.3
473 *
474 * @since 2.3
431475 *
432476 * @throws IllegalArgumentException if input is not valid base64 encoded data
433477 */
4040 */
4141 @SuppressWarnings("resource")
4242 public class JsonFactory
43 extends TokenStreamFactory
4344 implements Versioned,
4445 java.io.Serializable // since 2.1 (for Android, mostly)
4546 {
46 private static final long serialVersionUID = 1; // since 2.6.0
47 private static final long serialVersionUID = 2;
4748
4849 /*
4950 /**********************************************************
174175 */
175176 protected final static int DEFAULT_GENERATOR_FEATURE_FLAGS = JsonGenerator.Feature.collectDefaults();
176177
177 private final static SerializableString DEFAULT_ROOT_VALUE_SEPARATOR = DefaultPrettyPrinter.DEFAULT_ROOT_VALUE_SEPARATOR;
178
178 public final static SerializableString DEFAULT_ROOT_VALUE_SEPARATOR = DefaultPrettyPrinter.DEFAULT_ROOT_VALUE_SEPARATOR;
179
180 /**
181 * @since 2.10
182 */
183 public final static char DEFAULT_QUOTE_CHAR = '"';
184
179185 /*
180186 /**********************************************************
181187 /* Buffer, symbol table management
195201 *<p>
196202 * TODO: should clean up this; looks messy having 2 alternatives
197203 * with not very clear differences.
198 *
199 * @since 2.6.0
204 *
205 * @since 2.6
200206 */
201207 protected final transient ByteQuadsCanonicalizer _byteSymbolCanonicalizer = ByteQuadsCanonicalizer.createRoot();
202208
203209 /*
204210 /**********************************************************
205 /* Configuration
211 /* Configuration, simple feature flags
212 /**********************************************************
213 */
214
215 /**
216 * Currently enabled factory features.
217 */
218 protected int _factoryFeatures = DEFAULT_FACTORY_FEATURE_FLAGS;
219
220 /**
221 * Currently enabled parser features.
222 */
223 protected int _parserFeatures = DEFAULT_PARSER_FEATURE_FLAGS;
224
225 /**
226 * Currently enabled generator features.
227 */
228 protected int _generatorFeatures = DEFAULT_GENERATOR_FEATURE_FLAGS;
229
230 /*
231 /**********************************************************
232 /* Configuration, helper objects
206233 /**********************************************************
207234 */
208235
216243 protected ObjectCodec _objectCodec;
217244
218245 /**
219 * Currently enabled factory features.
220 */
221 protected int _factoryFeatures = DEFAULT_FACTORY_FEATURE_FLAGS;
222
223 /**
224 * Currently enabled parser features.
225 */
226 protected int _parserFeatures = DEFAULT_PARSER_FEATURE_FLAGS;
227
228 /**
229 * Currently enabled generator features.
230 */
231 protected int _generatorFeatures = DEFAULT_GENERATOR_FEATURE_FLAGS;
232
233 /**
234246 * Definition of custom character escapes to use for generators created
235247 * by this factory, if any. If null, standard data format specific
236248 * escapes are used.
257269 * @since 2.1
258270 */
259271 protected SerializableString _rootValueSeparator = DEFAULT_ROOT_VALUE_SEPARATOR;
260
272
273 /**
274 * Optional threshold used for automatically escaping character above certain character
275 * code value: either {@code 0} to indicate that no threshold is specified, or value
276 * at or above 127 to indicate last character code that is NOT automatically escaped
277 * (but depends on other configuration rules for checking).
278 *
279 * @since 2.10
280 */
281 protected int _maximumNonEscapedChar;
282
283 /**
284 * Character used for quoting field names (if field name quoting has not
285 * been disabled with {@link JsonWriteFeature#QUOTE_FIELD_NAMES})
286 * and JSON String values.
287 */
288 protected final char _quoteChar;
289
261290 /*
262291 /**********************************************************
263292 /* Construction
274303 * and this reuse only works within context of a single
275304 * factory instance.
276305 */
277 public JsonFactory() { this(null); }
278
279 public JsonFactory(ObjectCodec oc) { _objectCodec = oc; }
306 public JsonFactory() { this((ObjectCodec) null); }
307
308 public JsonFactory(ObjectCodec oc) {
309 _objectCodec = oc;
310 _quoteChar = DEFAULT_QUOTE_CHAR;
311 }
280312
281313 /**
282314 * Constructor used when copy()ing a factory instance.
286318 protected JsonFactory(JsonFactory src, ObjectCodec codec)
287319 {
288320 _objectCodec = codec;
321
322 // General
289323 _factoryFeatures = src._factoryFeatures;
290324 _parserFeatures = src._parserFeatures;
291325 _generatorFeatures = src._generatorFeatures;
292 _characterEscapes = src._characterEscapes;
293326 _inputDecorator = src._inputDecorator;
294327 _outputDecorator = src._outputDecorator;
328
329 // JSON-specific
330 _characterEscapes = src._characterEscapes;
295331 _rootValueSeparator = src._rootValueSeparator;
296
297 /* 27-Apr-2013, tatu: How about symbol table; should we try to
298 * reuse shared symbol tables? Could be more efficient that way;
299 * although can slightly add to concurrency overhead.
300 */
301 }
302
332 _maximumNonEscapedChar = src._maximumNonEscapedChar;
333 _quoteChar = src._quoteChar;
334 }
335
336 /**
337 * Constructor used by {@link JsonFactoryBuilder} for instantiation.
338 *
339 * @since 2.10
340 */
341 public JsonFactory(JsonFactoryBuilder b) {
342 _objectCodec = null;
343
344 // General
345 _factoryFeatures = b._factoryFeatures;
346 _parserFeatures = b._streamReadFeatures;
347 _generatorFeatures = b._streamWriteFeatures;
348 _inputDecorator = b._inputDecorator;
349 _outputDecorator = b._outputDecorator;
350
351 // JSON-specific
352 _characterEscapes = b._characterEscapes;
353 _rootValueSeparator = b._rootValueSeparator;
354 _maximumNonEscapedChar = b._maximumNonEscapedChar;
355 _quoteChar = b._quoteChar;
356 }
357
358 /**
359 * Constructor for subtypes; needed to work around the fact that before 3.0,
360 * this factory has cumbersome dual role as generic type as well as actual
361 * implementation for json.
362 *
363 * @param b Builder that contains information
364 * @param bogus Argument only needed to separate constructor signature; ignored
365 */
366 protected JsonFactory(TSFBuilder<?,?> b, boolean bogus) {
367 _objectCodec = null;
368
369 _factoryFeatures = b._factoryFeatures;
370 _parserFeatures = b._streamReadFeatures;
371 _generatorFeatures = b._streamWriteFeatures;
372 _inputDecorator = b._inputDecorator;
373 _outputDecorator = b._outputDecorator;
374
375 // JSON-specific: need to assign even if not really used
376 _characterEscapes = null;
377 _rootValueSeparator = null;
378 _maximumNonEscapedChar = 0;
379 _quoteChar = DEFAULT_QUOTE_CHAR;
380 }
381
382 /**
383 * Method that allows construction of differently configured factory, starting
384 * with settings of this factory.
385 *
386 * @since 2.10
387 */
388 public TSFBuilder<?,?> rebuild() {
389 // 13-Jun-2018, tatu: Verify sub-classing to prevent strange bugs in format impls
390 _requireJSONFactory("Factory implementation for format (%s) MUST override `rebuild()` method");
391 return new JsonFactoryBuilder(this);
392 }
393
394 /**
395 * Main factory method to use for constructing {@link JsonFactory} instances with
396 * different configuration: creates and returns a builder for collecting configuration
397 * settings; instance created by calling {@code build()} after all configuration
398 * set.
399 *<p>
400 * NOTE: signature unfortunately does not expose true implementation type; this
401 * will be fixed in 3.0.
402 */
403 public static TSFBuilder<?,?> builder() {
404 return new JsonFactoryBuilder();
405 }
406
303407 /**
304408 * Method for constructing a new {@link JsonFactory} that has
305409 * the same settings as this instance, but is otherwise
320424 // as per above, do clear ObjectCodec
321425 return new JsonFactory(this, null);
322426 }
323
324 /**
325 * @since 2.1
326 * @param exp
427
428 /**
429 * @since 2.1
327430 */
328431 protected void _checkInvalidCopy(Class<?> exp)
329432 {
353456 /* Capability introspection
354457 /**********************************************************
355458 */
356
459
357460 /**
358461 * Introspection method that higher-level functionality may call
359462 * to see whether underlying data format requires a stable ordering
369472 *
370473 * @since 2.3
371474 */
475 @Override
372476 public boolean requiresPropertyOrdering() { return false; }
373477
374478 /**
383487 *
384488 * @since 2.3
385489 */
490 @Override
386491 public boolean canHandleBinaryNatively() { return false; }
387492
388493 /**
407512 *
408513 * @since 2.9
409514 */
515 @Override
410516 public boolean canParseAsync() {
411517 // 31-May-2017, tatu: Jackson 2.9 does support async parsing for JSON,
412518 // but not all other formats, so need to do this:
413519 return _isJSONFactory();
414520 }
415521
416 /**
417 * Method for accessing kind of {@link FormatFeature} that a parser
418 * {@link JsonParser} produced by this factory would accept, if any;
419 * <code>null</code> returned if none.
420 *
421 * @since 2.6
422 */
522 @Override
423523 public Class<? extends FormatFeature> getFormatReadFeatureType() {
424524 return null;
425525 }
426526
427 /**
428 * Method for accessing kind of {@link FormatFeature} that a parser
429 * {@link JsonGenerator} produced by this factory would accept, if any;
430 * <code>null</code> returned if none.
431 *
432 * @since 2.6
433 */
527 @Override
434528 public Class<? extends FormatFeature> getFormatWriteFeatureType() {
435529 return null;
436530 }
531
437532 /*
438533 /**********************************************************
439534 /* Format detection functionality
450545 *
451546 * @since 2.1
452547 */
548 @Override
453549 public boolean canUseSchema(FormatSchema schema) {
454550 if (schema == null){
455551 return false;
465561 * Note: sub-classes should override this method; default
466562 * implementation will return null for all sub-classes
467563 */
564 @Override
468565 public String getFormatName()
469566 {
470567 /* Somewhat nasty check: since we can't make this abstract
536633 /**
537634 * Method for enabling or disabling specified parser feature
538635 * (check {@link JsonParser.Feature} for list of features)
539 */
636 *
637 * @deprecated since 2.10 use {@link JsonFactoryBuilder#configure(JsonFactory.Feature, boolean)} instead
638 */
639 @Deprecated
540640 public final JsonFactory configure(JsonFactory.Feature f, boolean state) {
541641 return state ? enable(f) : disable(f);
542642 }
544644 /**
545645 * Method for enabling specified parser feature
546646 * (check {@link JsonFactory.Feature} for list of features)
547 */
647 *
648 * @deprecated since 2.10 use {@link JsonFactoryBuilder#configure(JsonFactory.Feature, boolean)} instead
649 */
650 @Deprecated
548651 public JsonFactory enable(JsonFactory.Feature f) {
549652 _factoryFeatures |= f.getMask();
550653 return this;
553656 /**
554657 * Method for disabling specified parser features
555658 * (check {@link JsonFactory.Feature} for list of features)
556 */
659 *
660 * @deprecated since 2.10 use {@link JsonFactoryBuilder#configure(JsonFactory.Feature, boolean)} instead
661 */
662 @Deprecated
557663 public JsonFactory disable(JsonFactory.Feature f) {
558664 _factoryFeatures &= ~f.getMask();
559665 return this;
565671 public final boolean isEnabled(JsonFactory.Feature f) {
566672 return (_factoryFeatures & f.getMask()) != 0;
567673 }
568
674
675 @Override
676 public final int getParserFeatures() {
677 return _parserFeatures;
678 }
679
680 @Override
681 public final int getGeneratorFeatures() {
682 return _generatorFeatures;
683 }
684
685 // MUST be overridden by sub-classes that support format-specific parser features
686 @Override
687 public int getFormatParserFeatures() {
688 return 0;
689 }
690
691 // MUST be overridden by sub-classes that support format-specific generator features
692 @Override
693 public int getFormatGeneratorFeatures() {
694 return 0;
695 }
696
569697 /*
570698 /**********************************************************
571699 /* Configuration, parser configuration
572700 /**********************************************************
573701 */
574
702
575703 /**
576704 * Method for enabling or disabling specified parser feature
577705 * (check {@link JsonParser.Feature} for list of features)
601729 /**
602730 * Checked whether specified parser feature is enabled.
603731 */
732 @Override
604733 public final boolean isEnabled(JsonParser.Feature f) {
605734 return (_parserFeatures & f.getMask()) != 0;
606735 }
607736
608737 /**
738 * @since 2.10
739 */
740 public final boolean isEnabled(StreamReadFeature f) {
741 return (_parserFeatures & f.mappedFeature().getMask()) != 0;
742 }
743
744 /**
609745 * Method for getting currently configured input decorator (if any;
610746 * there is no default decorator).
611747 */
615751
616752 /**
617753 * Method for overriding currently configured input decorator
618 */
754 *
755 * @deprecated Since 2.10 use {@link JsonFactoryBuilder#inputDecorator(InputDecorator)} instead
756 */
757 @Deprecated
619758 public JsonFactory setInputDecorator(InputDecorator d) {
620759 _inputDecorator = d;
621760 return this;
635774 return state ? enable(f) : disable(f);
636775 }
637776
638
639777 /**
640778 * Method for enabling specified generator features
641779 * (check {@link JsonGenerator.Feature} for list of features)
657795 /**
658796 * Check whether specified generator feature is enabled.
659797 */
798 @Override
660799 public final boolean isEnabled(JsonGenerator.Feature f) {
661800 return (_generatorFeatures & f.getMask()) != 0;
662801 }
663802
803 /**
804 * @since 2.10
805 */
806 public final boolean isEnabled(StreamWriteFeature f) {
807 return (_generatorFeatures & f.mappedFeature().getMask()) != 0;
808 }
809
664810 /**
665811 * Method for accessing custom escapes factory uses for {@link JsonGenerator}s
666812 * it creates.
686832
687833 /**
688834 * Method for overriding currently configured output decorator
689 */
835 *
836 * @deprecated Since 2.10 use {@link JsonFactoryBuilder#inputDecorator(InputDecorator)} instead
837 */
838 @Deprecated
690839 public JsonFactory setOutputDecorator(OutputDecorator d) {
691840 _outputDecorator = d;
692841 return this;
759908 *
760909 * @since 2.1
761910 */
911 @Override
762912 public JsonParser createParser(File f) throws IOException, JsonParseException {
763913 // true, since we create InputStream from File
764914 IOContext ctxt = _createContext(f, true);
786936 *
787937 * @since 2.1
788938 */
939 @Override
789940 public JsonParser createParser(URL url) throws IOException, JsonParseException {
790941 // true, since we create InputStream from URL
791942 IOContext ctxt = _createContext(url, true);
800951 * The input stream will <b>not be owned</b> by
801952 * the parser, it will still be managed (i.e. closed if
802953 * end-of-stream is reacher, or parser close method called)
803 * if (and only if) {@link com.fasterxml.jackson.core.JsonParser.Feature#AUTO_CLOSE_SOURCE}
954 * if (and only if) {@link com.fasterxml.jackson.core.StreamReadFeature#AUTO_CLOSE_SOURCE}
804955 * is enabled.
805956 *<p>
806957 *
814965 *
815966 * @since 2.1
816967 */
968 @Override
817969 public JsonParser createParser(InputStream in) throws IOException, JsonParseException {
818970 IOContext ctxt = _createContext(in, false);
819971 return _createParser(_decorate(in, ctxt), ctxt);
820972 }
821973
974 /**
975 * Method for constructing parser for parsing
976 * the contents accessed via specified Reader.
977 <p>
978 * The read stream will <b>not be owned</b> by
979 * the parser, it will still be managed (i.e. closed if
980 * end-of-stream is reacher, or parser close method called)
981 * if (and only if) {@link com.fasterxml.jackson.core.StreamReadFeature#AUTO_CLOSE_SOURCE}
982 * is enabled.
983 *
984 * @param r Reader to use for reading JSON content to parse
985 *
986 * @since 2.1
987 */
988 @Override
989 public JsonParser createParser(Reader r) throws IOException, JsonParseException {
990 // false -> we do NOT own Reader (did not create it)
991 IOContext ctxt = _createContext(r, false);
992 return _createParser(_decorate(r, ctxt), ctxt);
993 }
994
995 /**
996 * Method for constructing parser for parsing
997 * the contents of given byte array.
998 *
999 * @since 2.1
1000 */
1001 @Override
1002 public JsonParser createParser(byte[] data) throws IOException, JsonParseException {
1003 IOContext ctxt = _createContext(data, true);
1004 if (_inputDecorator != null) {
1005 InputStream in = _inputDecorator.decorate(ctxt, data, 0, data.length);
1006 if (in != null) {
1007 return _createParser(in, ctxt);
1008 }
1009 }
1010 return _createParser(data, 0, data.length, ctxt);
1011 }
1012
1013 /**
1014 * Method for constructing parser for parsing
1015 * the contents of given byte array.
1016 *
1017 * @param data Buffer that contains data to parse
1018 * @param offset Offset of the first data byte within buffer
1019 * @param len Length of contents to parse within buffer
1020 *
1021 * @since 2.1
1022 */
1023 @Override
1024 public JsonParser createParser(byte[] data, int offset, int len) throws IOException, JsonParseException {
1025 IOContext ctxt = _createContext(data, true);
1026 // [JACKSON-512]: allow wrapping with InputDecorator
1027 if (_inputDecorator != null) {
1028 InputStream in = _inputDecorator.decorate(ctxt, data, offset, len);
1029 if (in != null) {
1030 return _createParser(in, ctxt);
1031 }
1032 }
1033 return _createParser(data, offset, len, ctxt);
1034 }
1035
1036 /**
1037 * Method for constructing parser for parsing
1038 * contents of given String.
1039 *
1040 * @since 2.1
1041 */
1042 @Override
1043 public JsonParser createParser(String content) throws IOException, JsonParseException {
1044 final int strLen = content.length();
1045 // Actually, let's use this for medium-sized content, up to 64kB chunk (32kb char)
1046 if ((_inputDecorator != null) || (strLen > 0x8000) || !canUseCharArrays()) {
1047 // easier to just wrap in a Reader than extend InputDecorator; or, if content
1048 // is too long for us to copy it over
1049 return createParser(new StringReader(content));
1050 }
1051 IOContext ctxt = _createContext(content, true);
1052 char[] buf = ctxt.allocTokenBuffer(strLen);
1053 content.getChars(0, strLen, buf, 0);
1054 return _createParser(buf, 0, strLen, ctxt, true);
1055 }
1056
1057 /**
1058 * Method for constructing parser for parsing
1059 * contents of given char array.
1060 *
1061 * @since 2.4
1062 */
1063 @Override
1064 public JsonParser createParser(char[] content) throws IOException {
1065 return createParser(content, 0, content.length);
1066 }
1067
1068 /**
1069 * Method for constructing parser for parsing contents of given char array.
1070 *
1071 * @since 2.4
1072 */
1073 @Override
1074 public JsonParser createParser(char[] content, int offset, int len) throws IOException {
1075 if (_inputDecorator != null) { // easier to just wrap in a Reader than extend InputDecorator
1076 return createParser(new CharArrayReader(content, offset, len));
1077 }
1078 return _createParser(content, offset, len, _createContext(content, true),
1079 // important: buffer is NOT recyclable, as it's from caller
1080 false);
1081 }
1082
1083 /**
1084 * Optional method for constructing parser for reading contents from specified {@link DataInput}
1085 * instance.
1086 *<p>
1087 * If this factory does not support {@link DataInput} as source,
1088 * will throw {@link UnsupportedOperationException}
1089 *
1090 * @since 2.8
1091 */
1092 @Override
1093 public JsonParser createParser(DataInput in) throws IOException {
1094 IOContext ctxt = _createContext(in, false);
1095 return _createParser(_decorate(in, ctxt), ctxt);
1096 }
1097
1098 /*
1099 /**********************************************************
1100 /* Parser factories, non-blocking (async) sources
1101 /**********************************************************
1102 */
1103
1104 /**
1105 * Optional method for constructing parser for non-blocking parsing
1106 * via {@link com.fasterxml.jackson.core.async.ByteArrayFeeder}
1107 * interface (accessed using {@link JsonParser#getNonBlockingInputFeeder()}
1108 * from constructed instance).
1109 *<p>
1110 * If this factory does not support non-blocking parsing (either at all,
1111 * or from byte array),
1112 * will throw {@link UnsupportedOperationException}
1113 *
1114 * @since 2.9
1115 */
1116 @Override
1117 public JsonParser createNonBlockingByteArrayParser() throws IOException
1118 {
1119 // 17-May-2017, tatu: Need to take care not to accidentally create JSON parser
1120 // for non-JSON input:
1121 _requireJSONFactory("Non-blocking source not (yet?) supported for this format (%s)");
1122 IOContext ctxt = _createNonBlockingContext(null);
1123 ByteQuadsCanonicalizer can = _byteSymbolCanonicalizer.makeChild(_factoryFeatures);
1124 return new NonBlockingJsonParser(ctxt, _parserFeatures, can);
1125 }
1126
1127 /*
1128 /**********************************************************
1129 /* Generator factories
1130 /**********************************************************
1131 */
1132
1133 /**
1134 * Method for constructing JSON generator for writing JSON content
1135 * using specified output stream.
1136 * Encoding to use must be specified, and needs to be one of available
1137 * types (as per JSON specification).
1138 *<p>
1139 * Underlying stream <b>is NOT owned</b> by the generator constructed,
1140 * so that generator will NOT close the output stream when
1141 * {@link JsonGenerator#close} is called (unless auto-closing
1142 * feature,
1143 * {@link com.fasterxml.jackson.core.JsonGenerator.Feature#AUTO_CLOSE_TARGET}
1144 * is enabled).
1145 * Using application needs to close it explicitly if this is the case.
1146 *<p>
1147 * Note: there are formats that use fixed encoding (like most binary data formats)
1148 * and that ignore passed in encoding.
1149 *
1150 * @param out OutputStream to use for writing JSON content
1151 * @param enc Character encoding to use
1152 *
1153 * @since 2.1
1154 */
1155 @Override
1156 public JsonGenerator createGenerator(OutputStream out, JsonEncoding enc)
1157 throws IOException
1158 {
1159 // false -> we won't manage the stream unless explicitly directed to
1160 IOContext ctxt = _createContext(out, false);
1161 ctxt.setEncoding(enc);
1162 if (enc == JsonEncoding.UTF8) {
1163 return _createUTF8Generator(_decorate(out, ctxt), ctxt);
1164 }
1165 Writer w = _createWriter(out, enc, ctxt);
1166 return _createGenerator(_decorate(w, ctxt), ctxt);
1167 }
1168
1169 /**
1170 * Convenience method for constructing generator that uses default
1171 * encoding of the format (UTF-8 for JSON and most other data formats).
1172 *<p>
1173 * Note: there are formats that use fixed encoding (like most binary data formats).
1174 *
1175 * @since 2.1
1176 */
1177 @Override
1178 public JsonGenerator createGenerator(OutputStream out) throws IOException {
1179 return createGenerator(out, JsonEncoding.UTF8);
1180 }
1181
1182 /**
1183 * Method for constructing JSON generator for writing JSON content
1184 * using specified Writer.
1185 *<p>
1186 * Underlying stream <b>is NOT owned</b> by the generator constructed,
1187 * so that generator will NOT close the Reader when
1188 * {@link JsonGenerator#close} is called (unless auto-closing
1189 * feature,
1190 * {@link com.fasterxml.jackson.core.JsonGenerator.Feature#AUTO_CLOSE_TARGET} is enabled).
1191 * Using application needs to close it explicitly.
1192 *
1193 * @since 2.1
1194 *
1195 * @param w Writer to use for writing JSON content
1196 */
1197 @Override
1198 public JsonGenerator createGenerator(Writer w) throws IOException {
1199 IOContext ctxt = _createContext(w, false);
1200 return _createGenerator(_decorate(w, ctxt), ctxt);
1201 }
1202
1203 /**
1204 * Method for constructing JSON generator for writing JSON content
1205 * to specified file, overwriting contents it might have (or creating
1206 * it if such file does not yet exist).
1207 * Encoding to use must be specified, and needs to be one of available
1208 * types (as per JSON specification).
1209 *<p>
1210 * Underlying stream <b>is owned</b> by the generator constructed,
1211 * i.e. generator will handle closing of file when
1212 * {@link JsonGenerator#close} is called.
1213 *
1214 * @param f File to write contents to
1215 * @param enc Character encoding to use
1216 *
1217 * @since 2.1
1218 */
1219 @Override
1220 public JsonGenerator createGenerator(File f, JsonEncoding enc) throws IOException
1221 {
1222 OutputStream out = new FileOutputStream(f);
1223 // true -> yes, we have to manage the stream since we created it
1224 IOContext ctxt = _createContext(out, true);
1225 ctxt.setEncoding(enc);
1226 if (enc == JsonEncoding.UTF8) {
1227 return _createUTF8Generator(_decorate(out, ctxt), ctxt);
1228 }
1229 Writer w = _createWriter(out, enc, ctxt);
1230 return _createGenerator(_decorate(w, ctxt), ctxt);
1231 }
1232
1233 /**
1234 * Method for constructing generator for writing content using specified
1235 * {@link DataOutput} instance.
1236 *
1237 * @since 2.8
1238 */
1239 @Override
1240 public JsonGenerator createGenerator(DataOutput out, JsonEncoding enc) throws IOException {
1241 return createGenerator(_createDataOutputWrapper(out), enc);
1242 }
1243
1244 /**
1245 * Convenience method for constructing generator that uses default
1246 * encoding of the format (UTF-8 for JSON and most other data formats).
1247 *<p>
1248 * Note: there are formats that use fixed encoding (like most binary data formats).
1249 *
1250 * @since 2.8
1251 */
1252 @Override
1253 public JsonGenerator createGenerator(DataOutput out) throws IOException {
1254 return createGenerator(_createDataOutputWrapper(out), JsonEncoding.UTF8);
1255 }
1256
1257 /*
1258 /**********************************************************
1259 /* Deprecated parser factory methods: to be removed from 3.x
1260 /**********************************************************
1261 */
1262
1263 /**
1264 * Method for constructing JSON parser instance to parse
1265 * contents of specified file.
1266 *<p>
1267 * Encoding is auto-detected from contents according to JSON
1268 * specification recommended mechanism. Json specification
1269 * supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
1270 * so auto-detection implemented only for this charsets.
1271 * For other charsets use {@link #createParser(java.io.Reader)}.
1272 *
1273 *<p>
1274 * Underlying input stream (needed for reading contents)
1275 * will be <b>owned</b> (and managed, i.e. closed as need be) by
1276 * the parser, since caller has no access to it.
1277 *
1278 * @param f File that contains JSON content to parse
1279 *
1280 * @deprecated Since 2.2, use {@link #createParser(File)} instead.
1281 */
1282 @Deprecated
1283 public JsonParser createJsonParser(File f) throws IOException, JsonParseException {
1284 return createParser(f);
1285 }
1286
1287 /**
1288 * Method for constructing JSON parser instance to parse
1289 * contents of resource reference by given URL.
1290 *
1291 *<p>
1292 * Encoding is auto-detected from contents according to JSON
1293 * specification recommended mechanism. Json specification
1294 * supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
1295 * so auto-detection implemented only for this charsets.
1296 * For other charsets use {@link #createParser(java.io.Reader)}.
1297 *
1298 *<p>
1299 * Underlying input stream (needed for reading contents)
1300 * will be <b>owned</b> (and managed, i.e. closed as need be) by
1301 * the parser, since caller has no access to it.
1302 *
1303 * @param url URL pointing to resource that contains JSON content to parse
1304 *
1305 * @deprecated Since 2.2, use {@link #createParser(URL)} instead.
1306 */
1307 @Deprecated
1308 public JsonParser createJsonParser(URL url) throws IOException, JsonParseException {
1309 return createParser(url);
1310 }
1311
1312 /**
1313 * Method for constructing JSON parser instance to parse
1314 * the contents accessed via specified input stream.
1315 *<p>
1316 * The input stream will <b>not be owned</b> by
1317 * the parser, it will still be managed (i.e. closed if
1318 * end-of-stream is reacher, or parser close method called)
1319 * if (and only if) {@link com.fasterxml.jackson.core.JsonParser.Feature#AUTO_CLOSE_SOURCE}
1320 * is enabled.
1321 *<p>
1322 *
1323 * Note: no encoding argument is taken since it can always be
1324 * auto-detected as suggested by JSON RFC. Json specification
1325 * supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
1326 * so auto-detection implemented only for this charsets.
1327 * For other charsets use {@link #createParser(java.io.Reader)}.
1328 *
1329 * @param in InputStream to use for reading JSON content to parse
1330 *
1331 * @deprecated Since 2.2, use {@link #createParser(InputStream)} instead.
1332 */
1333 @Deprecated
1334 public JsonParser createJsonParser(InputStream in) throws IOException, JsonParseException {
1335 return createParser(in);
1336 }
1337
8221338 /**
8231339 * Method for constructing parser for parsing
8241340 * the contents accessed via specified Reader.
8311347 *
8321348 * @param r Reader to use for reading JSON content to parse
8331349 *
834 * @since 2.1
835 */
836 public JsonParser createParser(Reader r) throws IOException, JsonParseException {
837 // false -> we do NOT own Reader (did not create it)
838 IOContext ctxt = _createContext(r, false);
839 return _createParser(_decorate(r, ctxt), ctxt);
840 }
841
842 /**
843 * Method for constructing parser for parsing
844 * the contents of given byte array.
845 *
846 * @since 2.1
847 */
848 public JsonParser createParser(byte[] data) throws IOException, JsonParseException {
849 IOContext ctxt = _createContext(data, true);
850 if (_inputDecorator != null) {
851 InputStream in = _inputDecorator.decorate(ctxt, data, 0, data.length);
852 if (in != null) {
853 return _createParser(in, ctxt);
854 }
855 }
856 return _createParser(data, 0, data.length, ctxt);
1350 * @deprecated Since 2.2, use {@link #createParser(Reader)} instead.
1351 */
1352 @Deprecated
1353 public JsonParser createJsonParser(Reader r) throws IOException, JsonParseException {
1354 return createParser(r);
1355 }
1356
1357 /**
1358 * Method for constructing parser for parsing the contents of given byte array.
1359 *
1360 * @deprecated Since 2.2, use {@link #createParser(byte[])} instead.
1361 */
1362 @Deprecated
1363 public JsonParser createJsonParser(byte[] data) throws IOException, JsonParseException {
1364 return createParser(data);
8571365 }
8581366
8591367 /**
8641372 * @param offset Offset of the first data byte within buffer
8651373 * @param len Length of contents to parse within buffer
8661374 *
867 * @since 2.1
868 */
869 public JsonParser createParser(byte[] data, int offset, int len) throws IOException, JsonParseException {
870 IOContext ctxt = _createContext(data, true);
871 // [JACKSON-512]: allow wrapping with InputDecorator
872 if (_inputDecorator != null) {
873 InputStream in = _inputDecorator.decorate(ctxt, data, offset, len);
874 if (in != null) {
875 return _createParser(in, ctxt);
876 }
877 }
878 return _createParser(data, offset, len, ctxt);
879 }
880
881 /**
882 * Method for constructing parser for parsing
883 * contents of given String.
884 *
885 * @since 2.1
886 */
887 public JsonParser createParser(String content) throws IOException, JsonParseException {
888 final int strLen = content.length();
889 // Actually, let's use this for medium-sized content, up to 64kB chunk (32kb char)
890 if ((_inputDecorator != null) || (strLen > 0x8000) || !canUseCharArrays()) {
891 // easier to just wrap in a Reader than extend InputDecorator; or, if content
892 // is too long for us to copy it over
893 return createParser(new StringReader(content));
894 }
895 IOContext ctxt = _createContext(content, true);
896 char[] buf = ctxt.allocTokenBuffer(strLen);
897 content.getChars(0, strLen, buf, 0);
898 return _createParser(buf, 0, strLen, ctxt, true);
899 }
900
901 /**
902 * Method for constructing parser for parsing
903 * contents of given char array.
904 *
905 * @since 2.4
906 */
907 public JsonParser createParser(char[] content) throws IOException {
908 return createParser(content, 0, content.length);
909 }
910
911 /**
912 * Method for constructing parser for parsing contents of given char array.
913 *
914 * @since 2.4
915 */
916 public JsonParser createParser(char[] content, int offset, int len) throws IOException {
917 if (_inputDecorator != null) { // easier to just wrap in a Reader than extend InputDecorator
918 return createParser(new CharArrayReader(content, offset, len));
919 }
920 return _createParser(content, offset, len, _createContext(content, true),
921 // important: buffer is NOT recyclable, as it's from caller
922 false);
923 }
924
925 /**
926 * Optional method for constructing parser for reading contents from specified {@link DataInput}
927 * instance.
928 *<p>
929 * If this factory does not support {@link DataInput} as source,
930 * will throw {@link UnsupportedOperationException}
931 *
932 * @since 2.8
933 */
934 public JsonParser createParser(DataInput in) throws IOException {
935 IOContext ctxt = _createContext(in, false);
936 return _createParser(_decorate(in, ctxt), ctxt);
937 }
938
939 /*
940 /**********************************************************
941 /* Parser factories, non-blocking (async) sources
942 /**********************************************************
943 */
944
945 /**
946 * Optional method for constructing parser for non-blocking parsing
947 * via {@link com.fasterxml.jackson.core.async.ByteArrayFeeder}
948 * interface (accessed using {@link JsonParser#getNonBlockingInputFeeder()}
949 * from constructed instance).
950 *<p>
951 * If this factory does not support non-blocking parsing (either at all,
952 * or from byte array),
953 * will throw {@link UnsupportedOperationException}
954 *
955 * @since 2.9
956 */
957 public JsonParser createNonBlockingByteArrayParser() throws IOException
958 {
959 // 17-May-2017, tatu: Need to take care not to accidentally create JSON parser
960 // for non-JSON input:
961 _requireJSONFactory("Non-blocking source not (yet?) support for this format (%s)");
962 IOContext ctxt = _createNonBlockingContext(null);
963 ByteQuadsCanonicalizer can = _byteSymbolCanonicalizer.makeChild(_factoryFeatures);
964 return new NonBlockingJsonParser(ctxt, _parserFeatures, can);
965 }
966
967 /*
968 /**********************************************************
969 /* Parser factories (old ones, pre-2.2)
970 /**********************************************************
971 */
972
973 /**
974 * Method for constructing JSON parser instance to parse
975 * contents of specified file.
976 *<p>
977 * Encoding is auto-detected from contents according to JSON
978 * specification recommended mechanism. Json specification
979 * supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
980 * so auto-detection implemented only for this charsets.
981 * For other charsets use {@link #createParser(java.io.Reader)}.
982 *
983 *<p>
984 * Underlying input stream (needed for reading contents)
985 * will be <b>owned</b> (and managed, i.e. closed as need be) by
986 * the parser, since caller has no access to it.
987 *
988 * @param f File that contains JSON content to parse
989 *
990 * @deprecated Since 2.2, use {@link #createParser(File)} instead.
991 */
992 @Deprecated
993 public JsonParser createJsonParser(File f) throws IOException, JsonParseException {
994 return createParser(f);
995 }
996
997 /**
998 * Method for constructing JSON parser instance to parse
999 * contents of resource reference by given URL.
1000 *
1001 *<p>
1002 * Encoding is auto-detected from contents according to JSON
1003 * specification recommended mechanism. Json specification
1004 * supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
1005 * so auto-detection implemented only for this charsets.
1006 * For other charsets use {@link #createParser(java.io.Reader)}.
1007 *
1008 *<p>
1009 * Underlying input stream (needed for reading contents)
1010 * will be <b>owned</b> (and managed, i.e. closed as need be) by
1011 * the parser, since caller has no access to it.
1012 *
1013 * @param url URL pointing to resource that contains JSON content to parse
1014 *
1015 * @deprecated Since 2.2, use {@link #createParser(URL)} instead.
1016 */
1017 @Deprecated
1018 public JsonParser createJsonParser(URL url) throws IOException, JsonParseException {
1019 return createParser(url);
1020 }
1021
1022 /**
1023 * Method for constructing JSON parser instance to parse
1024 * the contents accessed via specified input stream.
1025 *<p>
1026 * The input stream will <b>not be owned</b> by
1027 * the parser, it will still be managed (i.e. closed if
1028 * end-of-stream is reacher, or parser close method called)
1029 * if (and only if) {@link com.fasterxml.jackson.core.JsonParser.Feature#AUTO_CLOSE_SOURCE}
1030 * is enabled.
1031 *<p>
1032 *
1033 * Note: no encoding argument is taken since it can always be
1034 * auto-detected as suggested by JSON RFC. Json specification
1035 * supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
1036 * so auto-detection implemented only for this charsets.
1037 * For other charsets use {@link #createParser(java.io.Reader)}.
1038 *
1039 * @param in InputStream to use for reading JSON content to parse
1040 *
1041 * @deprecated Since 2.2, use {@link #createParser(InputStream)} instead.
1042 */
1043 @Deprecated
1044 public JsonParser createJsonParser(InputStream in) throws IOException, JsonParseException {
1045 return createParser(in);
1046 }
1047
1048 /**
1049 * Method for constructing parser for parsing
1050 * the contents accessed via specified Reader.
1051 <p>
1052 * The read stream will <b>not be owned</b> by
1053 * the parser, it will still be managed (i.e. closed if
1054 * end-of-stream is reacher, or parser close method called)
1055 * if (and only if) {@link com.fasterxml.jackson.core.JsonParser.Feature#AUTO_CLOSE_SOURCE}
1056 * is enabled.
1057 *
1058 * @param r Reader to use for reading JSON content to parse
1059 *
1060 * @deprecated Since 2.2, use {@link #createParser(Reader)} instead.
1061 */
1062 @Deprecated
1063 public JsonParser createJsonParser(Reader r) throws IOException, JsonParseException {
1064 return createParser(r);
1065 }
1066
1067 /**
1068 * Method for constructing parser for parsing the contents of given byte array.
1069 *
1070 * @deprecated Since 2.2, use {@link #createParser(byte[])} instead.
1071 */
1072 @Deprecated
1073 public JsonParser createJsonParser(byte[] data) throws IOException, JsonParseException {
1074 return createParser(data);
1075 }
1076
1077 /**
1078 * Method for constructing parser for parsing
1079 * the contents of given byte array.
1080 *
1081 * @param data Buffer that contains data to parse
1082 * @param offset Offset of the first data byte within buffer
1083 * @param len Length of contents to parse within buffer
1084 *
10851375 * @deprecated Since 2.2, use {@link #createParser(byte[],int,int)} instead.
10861376 */
10871377 @Deprecated
11021392
11031393 /*
11041394 /**********************************************************
1105 /* Generator factories, new (as per [Issue-25]
1395 /* Deprecated generator factory methods: to be removed from 3.x
11061396 /**********************************************************
11071397 */
11081398
11251415 *
11261416 * @param out OutputStream to use for writing JSON content
11271417 * @param enc Character encoding to use
1128 *
1129 * @since 2.1
1130 */
1131 public JsonGenerator createGenerator(OutputStream out, JsonEncoding enc)
1132 throws IOException
1133 {
1134 // false -> we won't manage the stream unless explicitly directed to
1135 IOContext ctxt = _createContext(out, false);
1136 ctxt.setEncoding(enc);
1137 if (enc == JsonEncoding.UTF8) {
1138 return _createUTF8Generator(_decorate(out, ctxt), ctxt);
1139 }
1140 Writer w = _createWriter(out, enc, ctxt);
1141 return _createGenerator(_decorate(w, ctxt), ctxt);
1142 }
1143
1144 /**
1145 * Convenience method for constructing generator that uses default
1146 * encoding of the format (UTF-8 for JSON and most other data formats).
1147 *<p>
1148 * Note: there are formats that use fixed encoding (like most binary data formats).
1149 *
1150 * @since 2.1
1151 */
1152 public JsonGenerator createGenerator(OutputStream out) throws IOException {
1153 return createGenerator(out, JsonEncoding.UTF8);
1154 }
1155
1418 *
1419 * @deprecated Since 2.2, use {@link #createGenerator(OutputStream, JsonEncoding)} instead.
1420 */
1421 @Deprecated
1422 public JsonGenerator createJsonGenerator(OutputStream out, JsonEncoding enc) throws IOException {
1423 return createGenerator(out, enc);
1424 }
1425
11561426 /**
11571427 * Method for constructing JSON generator for writing JSON content
11581428 * using specified Writer.
11631433 * feature,
11641434 * {@link com.fasterxml.jackson.core.JsonGenerator.Feature#AUTO_CLOSE_TARGET} is enabled).
11651435 * Using application needs to close it explicitly.
1166 *
1167 * @since 2.1
1168 *
1169 * @param w Writer to use for writing JSON content
1170 */
1171 public JsonGenerator createGenerator(Writer w) throws IOException {
1172 IOContext ctxt = _createContext(w, false);
1173 return _createGenerator(_decorate(w, ctxt), ctxt);
1174 }
1175
1176 /**
1177 * Method for constructing JSON generator for writing JSON content
1178 * to specified file, overwriting contents it might have (or creating
1179 * it if such file does not yet exist).
1180 * Encoding to use must be specified, and needs to be one of available
1181 * types (as per JSON specification).
1182 *<p>
1183 * Underlying stream <b>is owned</b> by the generator constructed,
1184 * i.e. generator will handle closing of file when
1185 * {@link JsonGenerator#close} is called.
1186 *
1187 * @param f File to write contents to
1188 * @param enc Character encoding to use
1189 *
1190 * @since 2.1
1191 */
1192 public JsonGenerator createGenerator(File f, JsonEncoding enc) throws IOException
1193 {
1194 OutputStream out = new FileOutputStream(f);
1195 // true -> yes, we have to manage the stream since we created it
1196 IOContext ctxt = _createContext(out, true);
1197 ctxt.setEncoding(enc);
1198 if (enc == JsonEncoding.UTF8) {
1199 return _createUTF8Generator(_decorate(out, ctxt), ctxt);
1200 }
1201 Writer w = _createWriter(out, enc, ctxt);
1202 return _createGenerator(_decorate(w, ctxt), ctxt);
1203 }
1204
1205 /**
1206 * Method for constructing generator for writing content using specified
1207 * {@link DataOutput} instance.
1208 *
1209 * @since 2.8
1210 */
1211 public JsonGenerator createGenerator(DataOutput out, JsonEncoding enc) throws IOException {
1212 return createGenerator(_createDataOutputWrapper(out), enc);
1213 }
1214
1215 /**
1216 * Convenience method for constructing generator that uses default
1217 * encoding of the format (UTF-8 for JSON and most other data formats).
1218 *<p>
1219 * Note: there are formats that use fixed encoding (like most binary data formats).
1220 *
1221 * @since 2.8
1222 */
1223 public JsonGenerator createGenerator(DataOutput out) throws IOException {
1224 return createGenerator(_createDataOutputWrapper(out), JsonEncoding.UTF8);
1225 }
1226
1227 /*
1228 /**********************************************************
1229 /* Generator factories, old (pre-2.2)
1230 /**********************************************************
1231 */
1232
1233 /**
1234 * Method for constructing JSON generator for writing JSON content
1235 * using specified output stream.
1236 * Encoding to use must be specified, and needs to be one of available
1237 * types (as per JSON specification).
1238 *<p>
1239 * Underlying stream <b>is NOT owned</b> by the generator constructed,
1240 * so that generator will NOT close the output stream when
1241 * {@link JsonGenerator#close} is called (unless auto-closing
1242 * feature,
1243 * {@link com.fasterxml.jackson.core.JsonGenerator.Feature#AUTO_CLOSE_TARGET}
1244 * is enabled).
1245 * Using application needs to close it explicitly if this is the case.
1246 *<p>
1247 * Note: there are formats that use fixed encoding (like most binary data formats)
1248 * and that ignore passed in encoding.
1249 *
1250 * @param out OutputStream to use for writing JSON content
1251 * @param enc Character encoding to use
1252 *
1253 * @deprecated Since 2.2, use {@link #createGenerator(OutputStream, JsonEncoding)} instead.
1254 */
1255 @Deprecated
1256 public JsonGenerator createJsonGenerator(OutputStream out, JsonEncoding enc) throws IOException {
1257 return createGenerator(out, enc);
1258 }
1259
1260 /**
1261 * Method for constructing JSON generator for writing JSON content
1262 * using specified Writer.
1263 *<p>
1264 * Underlying stream <b>is NOT owned</b> by the generator constructed,
1265 * so that generator will NOT close the Reader when
1266 * {@link JsonGenerator#close} is called (unless auto-closing
1267 * feature,
1268 * {@link com.fasterxml.jackson.core.JsonGenerator.Feature#AUTO_CLOSE_TARGET} is enabled).
1269 * Using application needs to close it explicitly.
12701436 *
12711437 * @param out Writer to use for writing JSON content
12721438 *
13711537 {
13721538 // 13-May-2016, tatu: Need to take care not to accidentally create JSON parser for
13731539 // non-JSON input.
1374 _requireJSONFactory("InputData source not (yet?) support for this format (%s)");
1540 _requireJSONFactory("InputData source not (yet?) supported for this format (%s)");
13751541 // Also: while we can't do full bootstrapping (due to read-ahead limitations), should
13761542 // at least handle possible UTF-8 BOM
13771543 int firstByte = ByteSourceJsonBootstrapper.skipUTF8BOM(input);
14001566 protected JsonGenerator _createGenerator(Writer out, IOContext ctxt) throws IOException
14011567 {
14021568 WriterBasedJsonGenerator gen = new WriterBasedJsonGenerator(ctxt,
1403 _generatorFeatures, _objectCodec, out);
1569 _generatorFeatures, _objectCodec, out, _quoteChar);
1570 if (_maximumNonEscapedChar > 0) {
1571 gen.setHighestNonEscapedChar(_maximumNonEscapedChar);
1572 }
14041573 if (_characterEscapes != null) {
14051574 gen.setCharacterEscapes(_characterEscapes);
14061575 }
14231592 */
14241593 protected JsonGenerator _createUTF8Generator(OutputStream out, IOContext ctxt) throws IOException {
14251594 UTF8JsonGenerator gen = new UTF8JsonGenerator(ctxt,
1426 _generatorFeatures, _objectCodec, out);
1595 _generatorFeatures, _objectCodec, out, _quoteChar);
1596 if (_maximumNonEscapedChar > 0) {
1597 gen.setHighestNonEscapedChar(_maximumNonEscapedChar);
1598 }
14271599 if (_characterEscapes != null) {
14281600 gen.setCharacterEscapes(_characterEscapes);
14291601 }
15141686 }
15151687 return out;
15161688 }
1517
1689
15181690 /*
15191691 /**********************************************************
15201692 /* Internal factory methods, other
15541726 * @since 2.9.7
15551727 */
15561728 protected IOContext _createNonBlockingContext(Object srcRef) {
1557 // [jackson-core#476]: disable buffer recycling for 2.9 to avoid concurrency issues;
1558 // easiest done by just constructing private "recycler":
1559 BufferRecycler recycler = new BufferRecycler();
1560 return new IOContext(recycler, srcRef, false);
1561 }
1562
1563 /**
1564 * @since 2.8
1565 */
1566 protected OutputStream _createDataOutputWrapper(DataOutput out) {
1567 return new DataOutputAsStream(out);
1568 }
1569
1570 /**
1571 * Helper methods used for constructing an optimal stream for
1572 * parsers to use, when input is to be read from an URL.
1573 * This helps when reading file content via URL.
1574 */
1575 protected InputStream _optimizedStreamFromURL(URL url) throws IOException {
1576 if ("file".equals(url.getProtocol())) {
1577 /* Can not do this if the path refers
1578 * to a network drive on windows. This fixes the problem;
1579 * might not be needed on all platforms (NFS?), but should not
1580 * matter a lot: performance penalty of extra wrapping is more
1581 * relevant when accessing local file system.
1582 */
1583 String host = url.getHost();
1584 if (host == null || host.length() == 0) {
1585 // [core#48]: Let's try to avoid probs with URL encoded stuff
1586 String path = url.getPath();
1587 if (path.indexOf('%') < 0) {
1588 return new FileInputStream(url.getPath());
1589
1590 }
1591 // otherwise, let's fall through and let URL decoder do its magic
1592 }
1593 }
1594 return url.openStream();
1729 // [jackson-core#479]: allow recycling for non-blocking parser again
1730 // now that access is thread-safe
1731 return new IOContext(_getBufferRecycler(), srcRef, false);
15951732 }
15961733
15971734 /*
0 package com.fasterxml.jackson.core;
1
2 import com.fasterxml.jackson.core.io.CharacterEscapes;
3 import com.fasterxml.jackson.core.io.SerializedString;
4 import com.fasterxml.jackson.core.json.JsonReadFeature;
5 import com.fasterxml.jackson.core.json.JsonWriteFeature;
6
7 /**
8 * {@link com.fasterxml.jackson.core.TSFBuilder}
9 * implementation for constructing vanilla {@link JsonFactory}
10 * instances for reading/writing JSON encoded content.
11 *<p>
12 * NOTE: as of Jackson 2.x, use of JSON-specific builder is bit cumbersome
13 * since {@link JsonFactory} serves dual duty of base class AND actual
14 * implementation for JSON backend. This will be fixed in Jackson 3.0.
15 *
16 * @since 2.10
17 */
18 public class JsonFactoryBuilder extends TSFBuilder<JsonFactory, JsonFactoryBuilder>
19 {
20 protected CharacterEscapes _characterEscapes;
21
22 protected SerializableString _rootValueSeparator;
23
24 protected int _maximumNonEscapedChar;
25
26 /**
27 * Character used for quoting field names (if field name quoting has not
28 * been disabled with {@link JsonWriteFeature#QUOTE_FIELD_NAMES})
29 * and JSON String values.
30 */
31 protected char _quoteChar = JsonFactory.DEFAULT_QUOTE_CHAR;
32
33 public JsonFactoryBuilder() {
34 super();
35 _rootValueSeparator = JsonFactory.DEFAULT_ROOT_VALUE_SEPARATOR;
36 _maximumNonEscapedChar = 0;
37 }
38
39 public JsonFactoryBuilder(JsonFactory base) {
40 super(base);
41 _characterEscapes = base.getCharacterEscapes();
42 _rootValueSeparator = base._rootValueSeparator;
43 _maximumNonEscapedChar = base._maximumNonEscapedChar;
44 }
45
46 /*
47 /**********************************************************
48 /* Mutators
49 /**********************************************************
50 */
51
52 // // // JSON-parsing features
53
54 @Override
55 public JsonFactoryBuilder enable(JsonReadFeature f) {
56 _legacyEnable(f.mappedFeature());
57 return this;
58 }
59
60 @Override
61 public JsonFactoryBuilder enable(JsonReadFeature first, JsonReadFeature... other) {
62 _legacyEnable(first.mappedFeature());
63 enable(first);
64 for (JsonReadFeature f : other) {
65 _legacyEnable(f.mappedFeature());
66 }
67 return this;
68 }
69
70 @Override
71 public JsonFactoryBuilder disable(JsonReadFeature f) {
72 _legacyDisable(f.mappedFeature());
73 return this;
74 }
75
76 @Override
77 public JsonFactoryBuilder disable(JsonReadFeature first, JsonReadFeature... other) {
78 _legacyDisable(first.mappedFeature());
79 for (JsonReadFeature f : other) {
80 _legacyEnable(f.mappedFeature());
81 }
82 return this;
83 }
84
85 @Override
86 public JsonFactoryBuilder configure(JsonReadFeature f, boolean state) {
87 return state ? enable(f) : disable(f);
88 }
89
90 // // // JSON-generating features
91
92 @Override
93 public JsonFactoryBuilder enable(JsonWriteFeature f) {
94 JsonGenerator.Feature old = f.mappedFeature();
95 if (old != null) {
96 _legacyEnable(old);
97 }
98 return this;
99 }
100
101 @Override
102 public JsonFactoryBuilder enable(JsonWriteFeature first, JsonWriteFeature... other) {
103 _legacyEnable(first.mappedFeature());
104 for (JsonWriteFeature f : other) {
105 _legacyEnable(f.mappedFeature());
106 }
107 return this;
108 }
109
110 @Override
111 public JsonFactoryBuilder disable(JsonWriteFeature f) {
112 _legacyDisable(f.mappedFeature());
113 return this;
114 }
115
116 @Override
117 public JsonFactoryBuilder disable(JsonWriteFeature first, JsonWriteFeature... other) {
118 _legacyDisable(first.mappedFeature());
119 for (JsonWriteFeature f : other) {
120 _legacyDisable(f.mappedFeature());
121 }
122 return this;
123 }
124
125 @Override
126 public JsonFactoryBuilder configure(JsonWriteFeature f, boolean state) {
127 return state ? enable(f) : disable(f);
128 }
129
130 // // // JSON-specific helper objects, settings
131
132 /**
133 * Method for defining custom escapes factory uses for {@link JsonGenerator}s
134 * it creates.
135 */
136 public JsonFactoryBuilder characterEscapes(CharacterEscapes esc) {
137 _characterEscapes = esc;
138 return this;
139 }
140
141 /**
142 * Method that allows overriding String used for separating root-level
143 * JSON values (default is single space character)
144 *
145 * @param sep Separator to use, if any; null means that no separator is
146 * automatically added
147 */
148 public JsonFactoryBuilder rootValueSeparator(String sep) {
149 _rootValueSeparator = (sep == null) ? null : new SerializedString(sep);
150 return this;
151 }
152
153 /**
154 * Method that allows overriding String used for separating root-level
155 * JSON values (default is single space character)
156 *
157 * @param sep Separator to use, if any; null means that no separator is
158 * automatically added
159 */
160 public JsonFactoryBuilder rootValueSeparator(SerializableString sep) {
161 _rootValueSeparator = sep;
162 return this;
163 }
164
165 /**
166 * Method that allows specifying threshold beyond which all characters are
167 * automatically escaped (without checking possible custom escaping settings
168 * a la {@link #characterEscapes}: for example, to force escaping of all non-ASCII
169 * characters (set to 127), or all non-Latin-1 character (set to 255).
170 * Default setting is "disabled", specified by passing value of {@code 0} (or
171 * negative numbers).
172 *<p>
173 * NOTE! Lowest legal value (aside from marker 0) is 127: for ASCII range, other checks apply
174 * and this threshold is ignored. If value between [1, 126] is specified, 127 will be
175 * used instead.
176 *
177 * @param maxNonEscaped Highest character code that is NOT automatically escaped; if
178 * positive value above 0, or 0 to indicate that no automatic escaping is applied
179 * beside from what JSON specification requires (and possible custom escape settings).
180 * Values between 1 and 127 are all taken to behave as if 127 is specified: that is,
181 * no automatic escaping is applied in ASCII range.
182 */
183 public JsonFactoryBuilder highestNonEscapedChar(int maxNonEscaped) {
184 _maximumNonEscapedChar = (maxNonEscaped <= 0) ? 0 : Math.max(127, maxNonEscaped);
185 return this;
186 }
187
188 /**
189 * Method that allows specifying an alternate
190 * character used for quoting field names (if field name quoting has not
191 * been disabled with {@link JsonWriteFeature#QUOTE_FIELD_NAMES})
192 * and JSON String values.
193 *<p>
194 * Default value is double-quote ({@code "}); typical alternative is
195 * single-quote/apostrophe ({@code '}).
196 *
197 * @param ch Character to use for quoting field names and JSON String values.
198 */
199 public JsonFactoryBuilder quoteChar(char ch) {
200 // 12-Aug-2019, tatu: Due to implementation details, escaping characters beyond
201 // 7-bit ASCII set has deep overhead so let's limit set. If we absolutely
202 // must it is possible of course, but leads to problems combining with
203 // custom escaping aspects.
204 if (ch > 0x7F) {
205 throw new IllegalArgumentException("Can only use Unicode characters up to 0x7F as quote characters");
206 }
207 _quoteChar = ch;
208 return this;
209 }
210
211 // // // Accessors for JSON-specific settings
212
213 public CharacterEscapes characterEscapes() { return _characterEscapes; }
214 public SerializableString rootValueSeparator() { return _rootValueSeparator; }
215
216 public int highestNonEscapedChar() { return _maximumNonEscapedChar; }
217
218 public char quoteChar() { return _quoteChar; }
219
220 @Override
221 public JsonFactory build() {
222 // 28-Dec-2017, tatu: No special settings beyond base class ones, so:
223 return new JsonFactory(this);
224 }
225 }
3333 */
3434 public enum Feature {
3535 // // Low-level I/O / content features
36
36
3737 /**
3838 * Feature that determines whether generator will automatically
3939 * close underlying output target that is NOT owned by the
8484 * occurs when used straight from Javascript.
8585 *<p>
8686 * Feature is enabled by default (since it is required by JSON specification).
87 *
88 * @deprecated Since 2.10 use {@link com.fasterxml.jackson.core.json.JsonWriteFeature#QUOTE_FIELD_NAMES} instead
8789 */
90 @Deprecated
8891 QUOTE_FIELD_NAMES(true),
8992
9093 /**
98101 * output.
99102 *<p>
100103 * Feature is enabled by default.
104 *
105 * @deprecated Since 2.10 use {@link com.fasterxml.jackson.core.json.JsonWriteFeature#WRITE_NAN_AS_STRINGS} instead
101106 */
107 @Deprecated
102108 QUOTE_NON_NUMERIC_NUMBERS(true),
103109
104 /**
105 * Feature that forces all Java numbers to be written as JSON strings.
106 * Default state is 'false', meaning that Java numbers are to
107 * be serialized using basic numeric serialization (as JSON
108 * numbers, integral or floating point). If enabled, all such
109 * numeric values are instead written out as JSON Strings.
110 *<p>
111 * One use case is to avoid problems with Javascript limitations:
112 * since Javascript standard specifies that all number handling
113 * should be done using 64-bit IEEE 754 floating point values,
114 * result being that some 64-bit integer values can not be
115 * accurately represent (as mantissa is only 51 bit wide).
116 *<p>
117 * Feature is disabled by default.
118 */
119 WRITE_NUMBERS_AS_STRINGS(false),
120
121 /**
122 * Feature that determines whether {@link java.math.BigDecimal} entries are
123 * serialized using {@link java.math.BigDecimal#toPlainString()} to prevent
124 * values to be written using scientific notation.
125 *<p>
126 * Feature is disabled by default, so default output mode is used; this generally
127 * depends on how {@link BigDecimal} has been created.
128 *
129 * @since 2.3
130 */
131 WRITE_BIGDECIMAL_AS_PLAIN(false),
132
110 // // Character escaping features
111
133112 /**
134113 * Feature that specifies that all characters beyond 7-bit ASCII
135114 * range (i.e. code points of 128 and above) need to be output
144123 * Put another way, effects of this feature are data-format specific.
145124 *<p>
146125 * Feature is disabled by default.
126 *
127 * @deprecated Since 2.10 use {@link com.fasterxml.jackson.core.json.JsonWriteFeature#ESCAPE_NON_ASCII} instead
147128 */
129 @Deprecated
148130 ESCAPE_NON_ASCII(false),
149131
150 // 23-Nov-2015, tatu: for [core#223], if and when it gets implemented
132 // // Datatype coercion features
133
151134 /**
152 * Feature that specifies handling of UTF-8 content that contains
153 * characters beyond BMP (Basic Multilingual Plane), which are
154 * represented in UCS-2 (Java internal character encoding) as two
155 * "surrogate" characters. If feature is enabled, these surrogate
156 * pairs are separately escaped using backslash escapes; if disabled,
157 * native output (4-byte UTF-8 sequence, or, with char-backed output
158 * targets, writing of surrogates as is which is typically converted
159 * by {@link java.io.Writer} into 4-byte UTF-8 sequence eventually)
160 * is used.
135 * Feature that forces all Java numbers to be written as Strings,
136 * even if the underlying data format has non-textual representation
137 * (which is the case for JSON as well as all binary formats).
138 * Default state is 'false', meaning that Java numbers are to
139 * be serialized using basic numeric serialization (as JSON
140 * numbers, integral or floating point, for example).
141 * If enabled, all such numeric values are instead written out as
142 * textual values (which for JSON means quoted in double-quotes).
161143 *<p>
162 * Note that the original JSON specification suggests use of escaping;
163 * but that this is not correct from standard UTF-8 handling perspective.
164 * Because of two competing goals, this feature was added to allow either
165 * behavior to be used, but defaulting to UTF-8 specification compliant
166 * mode.
144 * One use case is to avoid problems with Javascript limitations:
145 * since Javascript standard specifies that all number handling
146 * should be done using 64-bit IEEE 754 floating point values,
147 * result being that some 64-bit integer values can not be
148 * accurately represent (as mantissa is only 51 bit wide).
167149 *<p>
168150 * Feature is disabled by default.
169151 *
170 * @since Xxx
152 * @deprecated Since 2.10 use {@link com.fasterxml.jackson.core.json.JsonWriteFeature#WRITE_NUMBERS_AS_STRINGS} instead
171153 */
172 // ESCAPE_UTF8_SURROGATES(false),
173
154 @Deprecated
155 WRITE_NUMBERS_AS_STRINGS(false),
156
157 /**
158 * Feature that determines whether {@link java.math.BigDecimal} entries are
159 * serialized using {@link java.math.BigDecimal#toPlainString()} to prevent
160 * values to be written using scientific notation.
161 *<p>
162 * NOTE: only affects generators that serialize {@link java.math.BigDecimal}s
163 * using textual representation (textual formats but potentially some binary
164 * formats).
165 *<p>
166 * Feature is disabled by default, so default output mode is used; this generally
167 * depends on how {@link BigDecimal} has been created.
168 *
169 * @since 2.3
170 */
171 WRITE_BIGDECIMAL_AS_PLAIN(false),
172
174173 // // Schema/Validity support features
175174
176175 /**
329328 public abstract boolean isEnabled(Feature f);
330329
331330 /**
331 * @since 2.10
332 */
333 public boolean isEnabled(StreamWriteFeature f) {
334 return isEnabled(f.mappedFeature());
335 }
336
337 /**
332338 * Bulk access method for getting state of all standard (non-dataformat-specific)
333339 * {@link JsonGenerator.Feature}s.
334340 *
400406 * @since 2.6
401407 */
402408 public JsonGenerator overrideFormatFeatures(int values, int mask) {
403 throw new IllegalArgumentException("No FormatFeatures defined for generator of type "+getClass().getName());
404 /*
405 int oldState = getFeatureMask();
406 int newState = (oldState & ~mask) | (values & mask);
407 return setFeatureMask(newState);
408 */
409 // 08-Oct-2018, tatu: For 2.10 we actually do get `JsonWriteFeature`s, although they
410 // are (for 2.x only, not for 3.x) mapper to legacy settings. So do not freak out:
411 // throw new IllegalArgumentException("No FormatFeatures defined for generator of type "+getClass().getName());
412 return this;
409413 }
410414
411415 /*
516520 * simply return 0.
517521 *
518522 * @return Currently active limitation for highest non-escaped character,
519 * if defined; or -1 to indicate no additional escaping is performed.
523 * if defined; or 0 to indicate no additional escaping is performed.
520524 */
521525 public int getHighestEscapedChar() { return 0; }
522526
730734 */
731735 public abstract void writeStartArray() throws IOException;
732736
737 // TODO: deprecate in 2.11 (remove from 3.0)
733738 /**
734739 * Method for writing start marker of an Array value, similar
735740 * to {@link #writeStartArray()}, but also specifying how many
748753 public void writeStartArray(int size) throws IOException {
749754 writeStartArray();
750755 }
751
756
757 /**
758 * @since 2.10
759 */
760 public void writeStartArray(Object forValue) throws IOException {
761 writeStartArray();
762 setCurrentValue(forValue);
763 }
764
765 /**
766 * @since 2.10
767 */
768 public void writeStartArray(Object forValue, int size) throws IOException {
769 writeStartArray(size);
770 setCurrentValue(forValue);
771 }
772
752773 /**
753774 * Method for writing closing marker of a JSON Array value
754775 * (character ']'; plus possible white space decoration
760781 public abstract void writeEndArray() throws IOException;
761782
762783 /**
763 * Method for writing starting marker of a JSON Object value
784 * Method for writing starting marker of an Object value
764785 * (character '{'; plus possible white space decoration
765786 * if pretty-printing is enabled).
766787 *<p>
771792 public abstract void writeStartObject() throws IOException;
772793
773794 /**
774 * Method for writing starting marker of a JSON Object value
775 * (character '{'; plus possible white space decoration
776 * if pretty-printing is enabled), to represent Java given
777 * as the argument. Argument is offered as metadata, but more
795 * Method for writing starting marker of an Object value
796 * to represent the given Java Object value.
797 * Argument is offered as metadata, but more
778798 * importantly it should be assigned as the "current value"
779799 * for the Object content that gets constructed and initialized.
780800 *<p>
782802 * are allowed: meaning everywhere except for when
783803 * a field name is expected.
784804 *
785 * @since 2.8.
805 * @since 2.8
786806 */
787807 public void writeStartObject(Object forValue) throws IOException
788808 {
791811 }
792812
793813 /**
794 * Method for writing closing marker of a JSON Object value
814 * Method for writing starting marker of an Object value
815 * to represent the given Java Object value.
816 * Argument is offered as metadata, but more
817 * importantly it should be assigned as the "current value"
818 * for the Object content that gets constructed and initialized.
819 * In addition, caller knows number of key/value pairs ("properties")
820 * that will get written for the Object value: this is relevant for
821 * some format backends (but not, as an example, for JSON).
822 *<p>
823 * Object values can be written in any context where values
824 * are allowed: meaning everywhere except for when
825 * a field name is expected.
826 *
827 * @since 2.10
828 */
829 public void writeStartObject(Object forValue, int size) throws IOException
830 {
831 writeStartObject();
832 setCurrentValue(forValue);
833 }
834
835 /**
836 * Method for writing closing marker of an Object value
795837 * (character '}'; plus possible white space decoration
796838 * if pretty-printing is enabled).
797839 *<p>
10901132 *
10911133 * @since 2.1
10921134 */
1135 // public abstract void writeRaw(SerializableString raw) throws IOException;
10931136 public void writeRaw(SerializableString raw) throws IOException {
10941137 writeRaw(raw.getValue());
10951138 }
16951738
16961739 /**
16971740 * Convenience method for outputting a field entry ("member")
1698 * (that will contain a JSON Object value), and the START_OBJECT marker.
1741 * (that will contain an Object value), and the START_OBJECT marker.
16991742 * Equivalent to:
17001743 *<pre>
17011744 * writeFieldName(fieldName);
17551798 public void copyCurrentEvent(JsonParser p) throws IOException
17561799 {
17571800 JsonToken t = p.currentToken();
1758 // sanity check; what to do?
1759 if (t == null) {
1760 _reportError("No current event to copy");
1761 }
1762 switch (t.id()) {
1801 final int token = (t == null) ? ID_NOT_AVAILABLE : t.id();
1802 switch (token) {
17631803 case ID_NOT_AVAILABLE:
17641804 _reportError("No current event to copy");
17651805 break; // never gets here
18221862 writeObject(p.getEmbeddedObject());
18231863 break;
18241864 default:
1825 _throwInternal();
1865 throw new IllegalStateException("Internal error: unknown current token, "+t);
18261866 }
18271867 }
18281868
18591899 public void copyCurrentStructure(JsonParser p) throws IOException
18601900 {
18611901 JsonToken t = p.currentToken();
1862 if (t == null) {
1863 _reportError("No current event to copy");
1864 }
18651902 // Let's handle field-name separately first
1866 int id = t.id();
1903 int id = (t == null) ? ID_NOT_AVAILABLE : t.id();
18671904 if (id == ID_FIELD_NAME) {
18681905 writeFieldName(p.getCurrentName());
18691906 t = p.nextToken();
1870 id = t.id();
1907 id = (t == null) ? ID_NOT_AVAILABLE : t.id();
18711908 // fall-through to copy the associated value
18721909 }
18731910 switch (id) {
18741911 case ID_START_OBJECT:
18751912 writeStartObject();
1876 while (p.nextToken() != JsonToken.END_OBJECT) {
1877 copyCurrentStructure(p);
1878 }
1879 writeEndObject();
1880 break;
1913 _copyCurrentContents(p);
1914 return;
18811915 case ID_START_ARRAY:
18821916 writeStartArray();
1883 while (p.nextToken() != JsonToken.END_ARRAY) {
1884 copyCurrentStructure(p);
1885 }
1886 writeEndArray();
1887 break;
1917 _copyCurrentContents(p);
1918 return;
1919
18881920 default:
18891921 copyCurrentEvent(p);
1922 }
1923 }
1924
1925 /**
1926 * @since 2.10
1927 */
1928 protected void _copyCurrentContents(JsonParser p) throws IOException
1929 {
1930 int depth = 1;
1931 JsonToken t;
1932
1933 // Mostly copied from `copyCurrentEvent()`, but with added nesting counts
1934 while ((t = p.nextToken()) != null) {
1935 switch (t.id()) {
1936 case ID_FIELD_NAME:
1937 writeFieldName(p.getCurrentName());
1938 break;
1939
1940 case ID_START_ARRAY:
1941 writeStartArray();
1942 ++depth;
1943 break;
1944
1945 case ID_START_OBJECT:
1946 writeStartObject();
1947 ++depth;
1948 break;
1949
1950 case ID_END_ARRAY:
1951 writeEndArray();
1952 if (--depth == 0) {
1953 return;
1954 }
1955 break;
1956 case ID_END_OBJECT:
1957 writeEndObject();
1958 if (--depth == 0) {
1959 return;
1960 }
1961 break;
1962
1963 case ID_STRING:
1964 if (p.hasTextCharacters()) {
1965 writeString(p.getTextCharacters(), p.getTextOffset(), p.getTextLength());
1966 } else {
1967 writeString(p.getText());
1968 }
1969 break;
1970 case ID_NUMBER_INT:
1971 {
1972 NumberType n = p.getNumberType();
1973 if (n == NumberType.INT) {
1974 writeNumber(p.getIntValue());
1975 } else if (n == NumberType.BIG_INTEGER) {
1976 writeNumber(p.getBigIntegerValue());
1977 } else {
1978 writeNumber(p.getLongValue());
1979 }
1980 break;
1981 }
1982 case ID_NUMBER_FLOAT:
1983 {
1984 NumberType n = p.getNumberType();
1985 if (n == NumberType.BIG_DECIMAL) {
1986 writeNumber(p.getDecimalValue());
1987 } else if (n == NumberType.FLOAT) {
1988 writeNumber(p.getFloatValue());
1989 } else {
1990 writeNumber(p.getDoubleValue());
1991 }
1992 break;
1993 }
1994 case ID_TRUE:
1995 writeBoolean(true);
1996 break;
1997 case ID_FALSE:
1998 writeBoolean(false);
1999 break;
2000 case ID_NULL:
2001 writeNull();
2002 break;
2003 case ID_EMBEDDED_OBJECT:
2004 writeObject(p.getEmbeddedObject());
2005 break;
2006 default:
2007 throw new IllegalStateException("Internal error: unknown current token, "+t);
2008 }
18902009 }
18912010 }
18922011
44
55 package com.fasterxml.jackson.core;
66
7 import com.fasterxml.jackson.core.exc.StreamReadException;
78 import com.fasterxml.jackson.core.util.RequestPayload;
89
910 /**
1112 * (content that does not conform to JSON syntax as per specification)
1213 * is encountered.
1314 */
14 public class JsonParseException extends JsonProcessingException {
15 public class JsonParseException extends StreamReadException
16 {
1517 private static final long serialVersionUID = 2L; // 2.7
16
17 // transient since 2.7.4
18 protected transient JsonParser _processor;
19
20 /**
21 * Optional payload that can be assigned to pass along for error reporting
22 * or handling purposes. Core streaming parser implementations DO NOT
23 * initialize this; it is up to using applications and frameworks to
24 * populate it.
25 *
26 * @since 2.8
27 */
28 protected RequestPayload _requestPayload;
2918
3019 @Deprecated // since 2.7
3120 public JsonParseException(String msg, JsonLocation loc) {
32 super(msg, loc);
21 super(msg, loc, null);
3322 }
3423
3524 @Deprecated // since 2.7
4534 * @since 2.7
4635 */
4736 public JsonParseException(JsonParser p, String msg) {
48 super(msg, (p == null) ? null : p.getCurrentLocation());
49 _processor = p;
37 super(p, msg);
5038 }
5139
5240 /**
5341 * @since 2.7
5442 */
5543 public JsonParseException(JsonParser p, String msg, Throwable root) {
56 super(msg, (p == null) ? null : p.getCurrentLocation(), root);
57 _processor = p;
44 super(p, msg, root);
5845 }
5946
6047 /**
6148 * @since 2.7
6249 */
6350 public JsonParseException(JsonParser p, String msg, JsonLocation loc) {
64 super(msg, loc);
65 _processor = p;
51 super(p, msg, loc);
6652 }
6753
6854 /**
7056 */
7157 public JsonParseException(JsonParser p, String msg, JsonLocation loc, Throwable root) {
7258 super(msg, loc, root);
73 _processor = p;
7459 }
7560
7661 /**
8166 *
8267 * @since 2.7
8368 */
69 @Override
8470 public JsonParseException withParser(JsonParser p) {
8571 _processor = p;
8672 return this;
9480 *
9581 * @since 2.8
9682 */
83 @Override
9784 public JsonParseException withRequestPayload(RequestPayload p) {
9885 _requestPayload = p;
9986 return this;
10087 }
101
88
89 // NOTE: overloaded in 2.10 just to retain binary compatibility with 2.9 (remove from 3.0)
10290 @Override
10391 public JsonParser getProcessor() {
104 return _processor;
92 return super.getProcessor();
10593 }
10694
107 /**
108 * Method that may be called to find payload that was being parsed, if
109 * one was specified for parser that threw this Exception.
110 *
111 * @return request body, if payload was specified; `null` otherwise
112 *
113 * @since 2.8
114 */
95 // NOTE: overloaded in 2.10 just to retain binary compatibility with 2.9 (remove from 3.0)
96 @Override
11597 public RequestPayload getRequestPayload() {
116 return _requestPayload;
98 return super.getRequestPayload();
11799 }
118100
119 /**
120 * The method returns the String representation of the request payload if
121 * one was specified for parser that threw this Exception.
122 *
123 * @return request body as String, if payload was specified; `null` otherwise
124 *
125 * @since 2.8
126 */
101 // NOTE: overloaded in 2.10 just to retain binary compatibility with 2.9 (remove from 3.0)
102 @Override
127103 public String getRequestPayloadAsString() {
128 return (_requestPayload != null) ? _requestPayload.toString() : null;
104 return super.getRequestPayloadAsString();
129105 }
130106
131 /**
132 * Overriding the getMessage() to include the request body
133 */
107 // NOTE: overloaded in 2.10 just to retain binary compatibility with 2.9 (remove from 3.0)
134108 @Override
135109 public String getMessage() {
136 String msg = super.getMessage();
137 if (_requestPayload != null) {
138 msg += "\nRequest payload : " + _requestPayload.toString();
139 }
140 return msg;
110 return super.getMessage();
141111 }
142112 }
4242 * Enumeration that defines all on/off features for parsers.
4343 */
4444 public enum Feature {
45
4645 // // // Low-level I/O handling features:
47
46
4847 /**
4948 * Feature that determines whether parser will automatically
5049 * close underlying input source that is NOT owned by the
7271 * this is extensively used. As such, feature is
7372 * <b>disabled by default</b> for parsers and must be
7473 * explicitly enabled.
74 *<p>
75 * NOTE: while not technically deprecated, since 2.10 recommended to use
76 * {@link com.fasterxml.jackson.core.json.JsonReadFeature#ALLOW_JAVA_COMMENTS} instead.
7577 */
7678 ALLOW_COMMENTS(false),
7779
8688 * this is a non-standard feature. As such, feature is
8789 * <b>disabled by default</b> for parsers and must be
8890 * explicitly enabled.
91 *<p>
92 * NOTE: while not technically deprecated, since 2.10 recommended to use
93 * {@link com.fasterxml.jackson.core.json.JsonReadFeature#ALLOW_YAML_COMMENTS} instead.
8994 */
9095 ALLOW_YAML_COMMENTS(false),
91
96
9297 /**
9398 * Feature that determines whether parser will allow use
9499 * of unquoted field names (which is allowed by Javascript,
97102 * Since JSON specification requires use of double quotes for
98103 * field names,
99104 * this is a non-standard feature, and as such disabled by default.
105 *<p>
106 * NOTE: while not technically deprecated, since 2.10 recommended to use
107 * {@link com.fasterxml.jackson.core.json.JsonReadFeature#ALLOW_UNQUOTED_FIELD_NAMES} instead.
100108 */
101109 ALLOW_UNQUOTED_FIELD_NAMES(false),
102110
110118 * Since JSON specification requires use of double quotes for
111119 * field names,
112120 * this is a non-standard feature, and as such disabled by default.
121 *<p>
122 * NOTE: while not technically deprecated, since 2.10 recommended to use
123 * {@link com.fasterxml.jackson.core.json.JsonReadFeature#ALLOW_SINGLE_QUOTES} instead.
113124 */
114125 ALLOW_SINGLE_QUOTES(false),
115126
123134 *<p>
124135 * Since JSON specification requires quoting for all control characters,
125136 * this is a non-standard feature, and as such disabled by default.
137 *
138 * @deprecated Since 2.10 use {@link com.fasterxml.jackson.core.json.JsonReadFeature#ALLOW_UNESCAPED_CONTROL_CHARS} instead
126139 */
140 @Deprecated
127141 ALLOW_UNQUOTED_CONTROL_CHARS(false),
128142
129143 /**
134148 *<p>
135149 * Since JSON specification requires quoting for all control characters,
136150 * this is a non-standard feature, and as such disabled by default.
151 *
152 * @deprecated Since 2.10 use {@link com.fasterxml.jackson.core.json.JsonReadFeature#ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER} instead
137153 */
154 @Deprecated
138155 ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER(false),
139156
140157 /**
146163 *<p>
147164 * Since JSON specification does not allow leading zeroes,
148165 * this is a non-standard feature, and as such disabled by default.
166 *
167 * @deprecated Since 2.10 use {@link com.fasterxml.jackson.core.json.JsonReadFeature#ALLOW_LEADING_ZEROS_FOR_NUMBERS} instead
149168 */
169 @Deprecated
150170 ALLOW_NUMERIC_LEADING_ZEROS(false),
151171
152172 /**
166186 *<p>
167187 * Since JSON specification does not allow use of such values,
168188 * this is a non-standard feature, and as such disabled by default.
169 */
189 *
190 * @deprecated Since 2.10 use {@link com.fasterxml.jackson.core.json.JsonReadFeature#ALLOW_NON_NUMERIC_NUMBERS} instead
191 */
192 @Deprecated
170193 ALLOW_NON_NUMERIC_NUMBERS(false),
171194
172195 /**
184207 * feature and is disabled by default.
185208 *
186209 * @since 2.8
210 *
211 * @deprecated Since 2.10 use {@link com.fasterxml.jackson.core.json.JsonReadFeature#ALLOW_MISSING_VALUES} instead
187212 */
213 @Deprecated
188214 ALLOW_MISSING_VALUES(false),
189215
190216 /**
207233 * feature, and as such disabled by default.
208234 *
209235 * @since 2.9
236 *
237 * @deprecated Since 2.10 use {@link com.fasterxml.jackson.core.json.JsonReadFeature#ALLOW_TRAILING_COMMA} instead
210238 */
239 @Deprecated
211240 ALLOW_TRAILING_COMMA(false),
212241
213242 // // // Validity checks
276305 * @since 2.9
277306 */
278307 INCLUDE_SOURCE_IN_LOCATION(true),
279
308
280309 ;
281310
282311 /**
684713 public boolean isEnabled(Feature f) { return f.enabledIn(_features); }
685714
686715 /**
716 * Method for checking whether specified {@link Feature} is enabled.
717 *
718 * @since 2.10
719 */
720 public boolean isEnabled(StreamReadFeature f) { return f.mappedFeature().enabledIn(_features); }
721
722 /**
687723 * Bulk access method for getting state of all standard {@link Feature}s.
688724 *
689725 * @return Bit mask that defines current states of all standard {@link Feature}s.
753789 * @since 2.6
754790 */
755791 public JsonParser overrideFormatFeatures(int values, int mask) {
756 throw new IllegalArgumentException("No FormatFeatures defined for parser of type "+getClass().getName());
757 /*
758 _formatFeatures = (_formatFeatures & ~mask) | (values & mask);
759 */
792 // 08-Oct-2018, tatu: For 2.10 we actually do get `JsonReadFeature`s, although they
793 // are (for 2.x only, not for 3.x) mapper to legacy settings. So do not freak out:
794 // throw new IllegalArgumentException("No FormatFeatures defined for parser of type "+getClass().getName());
795 return this;
760796 }
761797
762798 /*
17631799 * Method for reading sequence of Objects from parser stream,
17641800 * all with same specified value type.
17651801 */
1766 public <T> Iterator<T> readValuesAs(TypeReference<?> valueTypeRef) throws IOException {
1802 public <T> Iterator<T> readValuesAs(TypeReference<T> valueTypeRef) throws IOException {
17671803 return _codec().readValues(this, valueTypeRef);
17681804 }
17691805
137137 public static JsonPointer valueOf(String input) { return compile(input); }
138138
139139 /**
140 * Accessor for an "empty" expression, that is, one you can get by
141 * calling {@link #compile} with "" (empty String).
142 *<p>
143 * NOTE: this is different from expression for {@code "/"} which would
144 * instead match Object node property with empty String ("") as name.
145 *
146 * @since 2.10
147 */
148 public static JsonPointer empty() { return EMPTY; }
149
150 /**
140151 * Factory method that will construct a pointer instance that describes
141152 * path to location given {@link JsonStreamContext} points to.
142153 *
247258 public boolean matches() { return _nextSegment == null; }
248259 public String getMatchingProperty() { return _matchingPropertyName; }
249260 public int getMatchingIndex() { return _matchingElementIndex; }
261
262 /**
263 * @return True if the root selector matches property name (that is, could
264 * match field value of JSON Object node)
265 */
250266 public boolean mayMatchProperty() { return _matchingPropertyName != null; }
267
268 /**
269 * @return True if the root selector matches element index (that is, could
270 * match an element of JSON Array node)
271 */
251272 public boolean mayMatchElement() { return _matchingElementIndex >= 0; }
252273
253274 /**
1818 protected JsonLocation _location;
1919
2020 protected JsonProcessingException(String msg, JsonLocation loc, Throwable rootCause) {
21 /* Argh. IOException(Throwable,String) is only available starting
22 * with JDK 1.6...
23 */
2421 super(msg);
2522 if (rootCause != null) {
2623 initCause(rootCause);
5555 * and specifically needs to be used if the root type is a
5656 * parameterized (generic) container type.
5757 */
58 public abstract <T> T readValue(JsonParser p, TypeReference<?> valueTypeRef)
58 public abstract <T> T readValue(JsonParser p, TypeReference<T> valueTypeRef)
5959 throws IOException;
6060
6161 /**
7878 * Method for reading sequence of Objects from parser stream,
7979 * all with same specified value type.
8080 */
81 public abstract <T> Iterator<T> readValues(JsonParser p, TypeReference<?> valueTypeRef)
81 public abstract <T> Iterator<T> readValues(JsonParser p, TypeReference<T> valueTypeRef)
8282 throws IOException;
8383
8484 /**
3030
3131 /**
3232 * Returns length of the (unquoted) String as characters.
33 * Functionally equvalent to:
33 * Functionally equivalent to:
3434 *<pre>
3535 * getValue().length();
3636 *</pre>
0 package com.fasterxml.jackson.core;
1
2 import java.io.InputStream;
3 import java.io.Reader;
4
5 /**
6 * Token reader (parser) features not-specific to any particular format backend.
7 * Eventual replacement for non-JSON-specific {@link com.fasterxml.jackson.core.JsonParser.Feature}s.
8 *
9 * @since 2.10
10 */
11 public enum StreamReadFeature
12 {
13 // // // Low-level I/O handling features:
14
15 /**
16 * Feature that determines whether parser will automatically
17 * close underlying input source that is NOT owned by the
18 * parser. If disabled, calling application has to separately
19 * close the underlying {@link InputStream} and {@link Reader}
20 * instances used to create the parser. If enabled, parser
21 * will handle closing, as long as parser itself gets closed:
22 * this happens when end-of-input is encountered, or parser
23 * is closed by a call to {@link JsonParser#close}.
24 *<p>
25 * Feature is enabled by default.
26 */
27 AUTO_CLOSE_SOURCE(JsonParser.Feature.AUTO_CLOSE_SOURCE),
28
29 // // // Validity checks
30
31 /**
32 * Feature that determines whether {@link JsonParser} will explicitly
33 * check that no duplicate JSON Object field names are encountered.
34 * If enabled, parser will check all names within context and report
35 * duplicates by throwing a {@link JsonParseException}; if disabled,
36 * parser will not do such checking. Assumption in latter case is
37 * that caller takes care of handling duplicates at a higher level:
38 * data-binding, for example, has features to specify detection to
39 * be done there.
40 *<p>
41 * Note that enabling this feature will incur performance overhead
42 * due to having to store and check additional information: this typically
43 * adds 20-30% to execution time for basic parsing.
44 */
45 STRICT_DUPLICATE_DETECTION(JsonParser.Feature.STRICT_DUPLICATE_DETECTION),
46
47 /**
48 * Feature that determines what to do if the underlying data format requires knowledge
49 * of all properties to decode (usually via a Schema), and if no definition is
50 * found for a property that input content contains.
51 * Typically most textual data formats do NOT require schema information (although
52 * some do, such as CSV), whereas many binary data formats do require definitions
53 * (such as Avro, protobuf), although not all (Smile, CBOR, BSON and MessagePack do not).
54 * Further note that some formats that do require schema information will not be able
55 * to ignore undefined properties: for example, Avro is fully positional and there is
56 * no possibility of undefined data. This leaves formats like Protobuf that have identifiers
57 * that may or may not map; and as such Protobuf format does make use of this feature.
58 *<p>
59 * Note that support for this feature is implemented by individual data format
60 * module, if (and only if) it makes sense for the format in question. For JSON,
61 * for example, this feature has no effect as properties need not be pre-defined.
62 *<p>
63 * Feature is disabled by default, meaning that if the underlying data format
64 * requires knowledge of all properties to output, attempts to read an unknown
65 * property will result in a {@link JsonProcessingException}
66 */
67 IGNORE_UNDEFINED(JsonParser.Feature.IGNORE_UNDEFINED),
68
69 // // // Other
70
71 /**
72 * Feature that determines whether {@link JsonLocation} instances should be constructed
73 * with reference to source or not. If source reference is included, its type and contents
74 * are included when `toString()` method is called (most notably when printing out parse
75 * exception with that location information). If feature is disabled, no source reference
76 * is passed and source is only indicated as "UNKNOWN".
77 *<p>
78 * Most common reason for disabling this feature is to avoid leaking information about
79 * internal information; this may be done for security reasons.
80 * Note that even if source reference is included, only parts of contents are usually
81 * printed, and not the whole contents. Further, many source reference types can not
82 * necessarily access contents (like streams), so only type is indicated, not contents.
83 *<p>
84 * Feature is enabled by default, meaning that "source reference" information is passed
85 * and some or all of the source content may be included in {@link JsonLocation} information
86 * constructed either when requested explicitly, or when needed for an exception.
87 */
88 INCLUDE_SOURCE_IN_LOCATION(JsonParser.Feature.INCLUDE_SOURCE_IN_LOCATION),
89
90 ;
91
92 /**
93 * Whether feature is enabled or disabled by default.
94 */
95 private final boolean _defaultState;
96
97 private final int _mask;
98
99 /**
100 * For backwards compatibility we may need to map to one of existing {@link JsonParser.Feature}s;
101 * if so, this is the feature to enable/disable.
102 */
103 final private JsonParser.Feature _mappedFeature;
104
105 private StreamReadFeature(JsonParser.Feature mapTo) {
106 // only for 2.x, let's map everything to legacy feature:
107 _mappedFeature = mapTo;
108 _mask = mapTo.getMask();
109 _defaultState = mapTo.enabledByDefault();
110 }
111
112 /**
113 * Method that calculates bit set (flags) of all features that
114 * are enabled by default.
115 */
116 public static int collectDefaults()
117 {
118 int flags = 0;
119 for (StreamReadFeature f : values()) {
120 if (f.enabledByDefault()) {
121 flags |= f.getMask();
122 }
123 }
124 return flags;
125 }
126
127 public boolean enabledByDefault() { return _defaultState; }
128 public boolean enabledIn(int flags) { return (flags & _mask) != 0; }
129 public int getMask() { return _mask; }
130
131 public JsonParser.Feature mappedFeature() { return _mappedFeature; }
132 }
0 package com.fasterxml.jackson.core;
1
2 import java.io.OutputStream;
3 import java.io.Writer;
4 import java.math.BigDecimal;
5
6 /**
7 * Token writer (generator) features not-specific to any particular format backend.
8 * Eventual replacement for non-JSON-specific {@link com.fasterxml.jackson.core.JsonGenerator.Feature}s.
9 *
10 * @since 2.10
11 */
12 public enum StreamWriteFeature
13 {
14 // // Low-level I/O / content features
15
16 /**
17 * Feature that determines whether generator will automatically
18 * close underlying output target that is NOT owned by the
19 * generator.
20 * If disabled, calling application has to separately
21 * close the underlying {@link OutputStream} and {@link Writer}
22 * instances used to create the generator. If enabled, generator
23 * will handle closing, as long as generator itself gets closed:
24 * this happens when end-of-input is encountered, or generator
25 * is closed by a call to {@link JsonGenerator#close}.
26 *<p>
27 * Feature is enabled by default.
28 */
29 AUTO_CLOSE_TARGET(JsonGenerator.Feature.AUTO_CLOSE_TARGET),
30
31 /**
32 * Feature that determines what happens when the generator is
33 * closed while there are still unmatched
34 * {@link JsonToken#START_ARRAY} or {@link JsonToken#START_OBJECT}
35 * entries in output content. If enabled, such Array(s) and/or
36 * Object(s) are automatically closed (that is, matching END_ token write
37 * call is made for all open scopes); if disabled, no additional
38 * write calls are made.
39 *<p>
40 * Feature is enabled by default.
41 */
42 AUTO_CLOSE_CONTENT(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT),
43
44 /**
45 * Feature that specifies that calls to {@link JsonGenerator#flush} will cause
46 * matching <code>flush()</code> to underlying {@link OutputStream}
47 * or {@link Writer}; if disabled this will not be done.
48 * Main reason to disable this feature is to prevent flushing at
49 * generator level, if it is not possible to prevent method being
50 * called by other code (like <code>ObjectMapper</code> or third
51 * party libraries).
52 *<p>
53 * Feature is enabled by default.
54 */
55 FLUSH_PASSED_TO_STREAM(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM),
56
57 // // Datatype coercion features
58
59 /**
60 * Feature that determines whether {@link java.math.BigDecimal} entries are
61 * serialized using {@link java.math.BigDecimal#toPlainString()} to prevent
62 * values to be written using scientific notation.
63 *<p>
64 * NOTE: only affects generators that serialize {@link java.math.BigDecimal}s
65 * using textual representation (textual formats but potentially some binary
66 * formats).
67 *<p>
68 * Feature is disabled by default, so default output mode is used; this generally
69 * depends on how {@link BigDecimal} has been created.
70 */
71 WRITE_BIGDECIMAL_AS_PLAIN(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN),
72
73 // // Schema/Validity support features
74
75 /**
76 * Feature that determines whether {@link JsonGenerator} will explicitly
77 * check that no duplicate JSON Object field names are written.
78 * If enabled, generator will check all names within context and report
79 * duplicates by throwing a {@link JsonGenerationException}; if disabled,
80 * no such checking will be done. Assumption in latter case is
81 * that caller takes care of not trying to write duplicate names.
82 *<p>
83 * Note that enabling this feature will incur performance overhead
84 * due to having to store and check additional information.
85 *<p>
86 * Feature is disabled by default.
87 */
88 STRICT_DUPLICATE_DETECTION(JsonGenerator.Feature.STRICT_DUPLICATE_DETECTION),
89
90 /**
91 * Feature that determines what to do if the underlying data format requires knowledge
92 * of all properties to output, and if no definition is found for a property that
93 * caller tries to write. If enabled, such properties will be quietly ignored;
94 * if disabled, a {@link JsonProcessingException} will be thrown to indicate the
95 * problem.
96 * Typically most textual data formats do NOT require schema information (although
97 * some do, such as CSV), whereas many binary data formats do require definitions
98 * (such as Avro, protobuf), although not all (Smile, CBOR, BSON and MessagePack do not).
99 *<p>
100 * Note that support for this feature is implemented by individual data format
101 * module, if (and only if) it makes sense for the format in question. For JSON,
102 * for example, this feature has no effect as properties need not be pre-defined.
103 *<p>
104 * Feature is disabled by default, meaning that if the underlying data format
105 * requires knowledge of all properties to output, attempts to write an unknown
106 * property will result in a {@link JsonProcessingException}
107 */
108 IGNORE_UNKNOWN(JsonGenerator.Feature.IGNORE_UNKNOWN),
109 ;
110
111 /**
112 * Whether feature is enabled or disabled by default.
113 */
114 private final boolean _defaultState;
115
116 private final int _mask;
117
118 /**
119 * For backwards compatibility we may need to map to one of existing {@link JsonParser.Feature}s;
120 * if so, this is the feature to enable/disable.
121 */
122 final private JsonGenerator.Feature _mappedFeature;
123
124 private StreamWriteFeature(JsonGenerator.Feature mappedTo) {
125 // only for 2.x, let's map everything to legacy feature:
126 _mappedFeature = mappedTo;
127 _mask = mappedTo.getMask();
128 _defaultState = mappedTo.enabledByDefault();
129 }
130
131 /**
132 * Method that calculates bit set (flags) of all features that
133 * are enabled by default.
134 */
135 public static int collectDefaults()
136 {
137 int flags = 0;
138 for (StreamWriteFeature f : values()) {
139 if (f.enabledByDefault()) {
140 flags |= f.getMask();
141 }
142 }
143 return flags;
144 }
145
146 public boolean enabledByDefault() { return _defaultState; }
147 public boolean enabledIn(int flags) { return (flags & _mask) != 0; }
148 public int getMask() { return _mask; }
149
150 public JsonGenerator.Feature mappedFeature() { return _mappedFeature; }
151 }
0 package com.fasterxml.jackson.core;
1
2 import com.fasterxml.jackson.core.io.InputDecorator;
3 import com.fasterxml.jackson.core.io.OutputDecorator;
4 import com.fasterxml.jackson.core.json.JsonReadFeature;
5 import com.fasterxml.jackson.core.json.JsonWriteFeature;
6
7 /**
8 * Since 2.10, Builder class is offered for creating token stream factories
9 * with difference configurations: with 3.x they will be fully immutable.
10 *
11 * @since 2.10
12 */
13 public abstract class TSFBuilder<F extends JsonFactory,
14 B extends TSFBuilder<F,B>>
15 {
16 /*
17 /**********************************************************************
18 /* Constants
19 /**********************************************************************
20 */
21
22 /**
23 * Bitfield (set of flags) of all factory features that are enabled by default.
24 */
25 protected final static int DEFAULT_FACTORY_FEATURE_FLAGS = JsonFactory.Feature.collectDefaults();
26
27 /**
28 * Bitfield (set of flags) of all parser features that are enabled
29 * by default.
30 */
31 protected final static int DEFAULT_PARSER_FEATURE_FLAGS = JsonParser.Feature.collectDefaults();
32
33 /**
34 * Bitfield (set of flags) of all generator features that are enabled
35 * by default.
36 */
37 protected final static int DEFAULT_GENERATOR_FEATURE_FLAGS = JsonGenerator.Feature.collectDefaults();
38
39 /*
40 /**********************************************************************
41 /* Configured features
42 /**********************************************************************
43 */
44
45 /**
46 * Set of {@link TokenStreamFactory.Feature}s enabled, as bitmask.
47 */
48 protected int _factoryFeatures;
49
50 /**
51 * Set of {@link JsonParser.Feature}s enabled, as bitmask.
52 */
53 protected int _streamReadFeatures;
54
55 /**
56 * Set of {@link JsonGenerator.Feature}s enabled, as bitmask.
57 */
58 protected int _streamWriteFeatures;
59
60 /*
61 /**********************************************************************
62 /* Other configuration
63 /**********************************************************************
64 */
65
66 /**
67 * Optional helper object that may decorate input sources, to do
68 * additional processing on input during parsing.
69 */
70 protected InputDecorator _inputDecorator;
71
72 /**
73 * Optional helper object that may decorate output object, to do
74 * additional processing on output during content generation.
75 */
76 protected OutputDecorator _outputDecorator;
77
78 /*
79 /**********************************************************************
80 /* Construction
81 /**********************************************************************
82 */
83
84 protected TSFBuilder() {
85 _factoryFeatures = DEFAULT_FACTORY_FEATURE_FLAGS;
86 _streamReadFeatures = DEFAULT_PARSER_FEATURE_FLAGS;
87 _streamWriteFeatures = DEFAULT_GENERATOR_FEATURE_FLAGS;
88 _inputDecorator = null;
89 _outputDecorator = null;
90 }
91
92 protected TSFBuilder(JsonFactory base)
93 {
94 this(base._factoryFeatures,
95 base._parserFeatures, base._generatorFeatures);
96 }
97
98 protected TSFBuilder(int factoryFeatures,
99 int parserFeatures, int generatorFeatures)
100 {
101 _factoryFeatures = factoryFeatures;
102 _streamReadFeatures = parserFeatures;
103 _streamWriteFeatures = generatorFeatures;
104 }
105
106 // // // Accessors
107
108 public int factoryFeaturesMask() { return _factoryFeatures; }
109 public int streamReadFeatures() { return _streamReadFeatures; }
110 public int streamWriteFeatures() { return _streamWriteFeatures; }
111
112 public InputDecorator inputDecorator() { return _inputDecorator; }
113 public OutputDecorator outputDecorator() { return _outputDecorator; }
114
115 // // // Factory features
116
117 public B enable(JsonFactory.Feature f) {
118 _factoryFeatures |= f.getMask();
119 return _this();
120 }
121
122 public B disable(JsonFactory.Feature f) {
123 _factoryFeatures &= ~f.getMask();
124 return _this();
125 }
126
127 public B configure(JsonFactory.Feature f, boolean state) {
128 return state ? enable(f) : disable(f);
129 }
130
131 // // // StreamReadFeatures (replacement of non-json-specific parser features)
132
133 public B enable(StreamReadFeature f) {
134 _streamReadFeatures |= f.mappedFeature().getMask();
135 return _this();
136 }
137
138 public B enable(StreamReadFeature first, StreamReadFeature... other) {
139 _streamReadFeatures |= first.mappedFeature().getMask();
140 for (StreamReadFeature f : other) {
141 _streamReadFeatures |= f.mappedFeature().getMask();
142 }
143 return _this();
144 }
145
146 public B disable(StreamReadFeature f) {
147 _streamReadFeatures &= ~f.mappedFeature().getMask();
148 return _this();
149 }
150
151 public B disable(StreamReadFeature first, StreamReadFeature... other) {
152 _streamReadFeatures &= ~first.mappedFeature().getMask();
153 for (StreamReadFeature f : other) {
154 _streamReadFeatures &= ~f.mappedFeature().getMask();
155 }
156 return _this();
157 }
158
159 public B configure(StreamReadFeature f, boolean state) {
160 return state ? enable(f) : disable(f);
161 }
162
163 // // // StreamWriteFeatures (replacement of non-json-specific generator features)
164
165 public B enable(StreamWriteFeature f) {
166 _streamWriteFeatures |= f.mappedFeature().getMask();
167 return _this();
168 }
169
170 public B enable(StreamWriteFeature first, StreamWriteFeature... other) {
171 _streamWriteFeatures |= first.mappedFeature().getMask();
172 for (StreamWriteFeature f : other) {
173 _streamWriteFeatures |= f.mappedFeature().getMask();
174 }
175 return _this();
176 }
177
178 public B disable(StreamWriteFeature f) {
179 _streamWriteFeatures &= ~f.mappedFeature().getMask();
180 return _this();
181 }
182
183 public B disable(StreamWriteFeature first, StreamWriteFeature... other) {
184 _streamWriteFeatures &= ~first.mappedFeature().getMask();
185 for (StreamWriteFeature f : other) {
186 _streamWriteFeatures &= ~f.mappedFeature().getMask();
187 }
188 return _this();
189 }
190
191 public B configure(StreamWriteFeature f, boolean state) {
192 return state ? enable(f) : disable(f);
193 }
194
195 /* 26-Jun-2018, tatu: This should not be needed here, but due to 2.x limitations,
196 * we do need to include it or require casting.
197 * Specifically: since `JsonFactory` (and not `TokenStreamFactory`) is base class
198 * for all backends, it can not expose JSON-specific builder, but this.
199 * So let's select lesser evil(s).
200 */
201
202 // // // JSON-specific, reads
203
204 public B enable(JsonReadFeature f) {
205 return _failNonJSON(f);
206 }
207
208 public B enable(JsonReadFeature first, JsonReadFeature... other) {
209 return _failNonJSON(first);
210 }
211
212 public B disable(JsonReadFeature f) {
213 return _failNonJSON(f);
214 }
215
216 public B disable(JsonReadFeature first, JsonReadFeature... other) {
217 return _failNonJSON(first);
218 }
219
220 public B configure(JsonReadFeature f, boolean state) {
221 return _failNonJSON(f);
222 }
223
224 private B _failNonJSON(Object feature) {
225 throw new IllegalArgumentException("Feature "+feature.getClass().getName()
226 +"#"+feature.toString()+" not supported for non-JSON backend");
227 }
228
229 // // // JSON-specific, writes
230
231 public B enable(JsonWriteFeature f) {
232 return _failNonJSON(f);
233 }
234
235 public B enable(JsonWriteFeature first, JsonWriteFeature... other) {
236 return _failNonJSON(first);
237 }
238
239 public B disable(JsonWriteFeature f) {
240 return _failNonJSON(f);
241 }
242
243 public B disable(JsonWriteFeature first, JsonWriteFeature... other) {
244 return _failNonJSON(first);
245 }
246
247 public B configure(JsonWriteFeature f, boolean state) {
248 return _failNonJSON(f);
249 }
250
251 // // // Other configuration
252
253 public B inputDecorator(InputDecorator dec) {
254 _inputDecorator = dec;
255 return _this();
256 }
257
258 public B outputDecorator(OutputDecorator dec) {
259 _outputDecorator = dec;
260 return _this();
261 }
262
263 // // // Other methods
264
265 /**
266 * Method for constructing actual {@link TokenStreamFactory} instance, given
267 * configuration.
268 */
269 public abstract F build();
270
271 // silly convenience cast method we need
272 @SuppressWarnings("unchecked")
273 protected final B _this() { return (B) this; }
274
275 // // // Support for subtypes
276
277 protected void _legacyEnable(JsonParser.Feature f) {
278 _streamReadFeatures |= f.getMask();
279 }
280 protected void _legacyDisable(JsonParser.Feature f) {
281 _streamReadFeatures &= ~f.getMask();
282 }
283
284 protected void _legacyEnable(JsonGenerator.Feature f) {
285 _streamWriteFeatures |= f.getMask();
286 }
287 protected void _legacyDisable(JsonGenerator.Feature f) {
288 _streamWriteFeatures &= ~f.getMask();
289 }
290 }
0 package com.fasterxml.jackson.core;
1
2 import java.io.*;
3 import java.net.URL;
4
5 import com.fasterxml.jackson.core.io.DataOutputAsStream;
6
7 /**
8 * Intermediate base class for actual format-specific factories for constructing
9 * parsers (reading) and generators (writing). Although full power will only be
10 * available with Jackson 3, skeletal implementation added in 2.10 to help conversion
11 * of code for 2.x to 3.x migration of projects depending on Jackson
12 *
13 * @since 2.10
14 */
15 public abstract class TokenStreamFactory
16 implements Versioned,
17 java.io.Serializable
18 {
19 private static final long serialVersionUID = 2;
20
21 /*
22 /**********************************************************
23 /* Capability introspection
24 /**********************************************************
25 */
26
27 /**
28 * Introspection method that higher-level functionality may call
29 * to see whether underlying data format requires a stable ordering
30 * of object properties or not.
31 * This is usually used for determining
32 * whether to force a stable ordering (like alphabetic ordering by name)
33 * if no ordering if explicitly specified.
34 *<p>
35 * Default implementation returns <code>false</code> as JSON does NOT
36 * require stable ordering. Formats that require ordering include positional
37 * textual formats like <code>CSV</code>, and schema-based binary formats
38 * like <code>Avro</code>.
39 */
40 public abstract boolean requiresPropertyOrdering();
41
42 /**
43 * Introspection method that higher-level functionality may call
44 * to see whether underlying data format can read and write binary
45 * data natively; that is, embeded it as-is without using encodings
46 * such as Base64.
47 *<p>
48 * Default implementation returns <code>false</code> as JSON does not
49 * support native access: all binary content must use Base64 encoding.
50 * Most binary formats (like Smile and Avro) support native binary content.
51 */
52 public abstract boolean canHandleBinaryNatively();
53
54 /**
55 * Introspection method that can be used to check whether this
56 * factory can create non-blocking parsers: parsers that do not
57 * use blocking I/O abstractions but instead use a
58 * {@link com.fasterxml.jackson.core.async.NonBlockingInputFeeder}.
59 */
60 public abstract boolean canParseAsync();
61
62 /**
63 * Method for accessing kind of {@link FormatFeature} that a parser
64 * {@link JsonParser} produced by this factory would accept, if any;
65 * <code>null</code> returned if none.
66 *
67 * @since 2.6
68 */
69 public abstract Class<? extends FormatFeature> getFormatReadFeatureType();
70
71 /**
72 * Method for accessing kind of {@link FormatFeature} that a parser
73 * {@link JsonGenerator} produced by this factory would accept, if any;
74 * <code>null</code> returned if none.
75 *
76 * @since 2.6
77 */
78 public abstract Class<? extends FormatFeature> getFormatWriteFeatureType();
79
80 /*
81 /**********************************************************
82 /* Format detection functionality
83 /**********************************************************
84 */
85
86 /**
87 * Method that can be used to quickly check whether given schema
88 * is something that parsers and/or generators constructed by this
89 * factory could use. Note that this means possible use, at the level
90 * of data format (i.e. schema is for same data format as parsers and
91 * generators this factory constructs); individual schema instances
92 * may have further usage restrictions.
93 *
94 * @since 2.1
95 */
96 public abstract boolean canUseSchema(FormatSchema schema);
97
98 /**
99 * Method that returns short textual id identifying format
100 * this factory supports.
101 */
102 public abstract String getFormatName();
103
104 /*
105 /**********************************************************
106 /* Configuration access
107 /**********************************************************
108 */
109
110 public abstract boolean isEnabled(JsonParser.Feature f);
111 public abstract boolean isEnabled(JsonGenerator.Feature f);
112
113 public abstract int getParserFeatures();
114 public abstract int getGeneratorFeatures();
115
116 public abstract int getFormatParserFeatures();
117 public abstract int getFormatGeneratorFeatures();
118
119 /*
120 /**********************************************************
121 /* Factory methods, parsers
122 /**********************************************************
123 */
124
125 public abstract JsonParser createParser(byte[] data) throws IOException;
126 public abstract JsonParser createParser(byte[] data, int offset, int len) throws IOException;
127 public abstract JsonParser createParser(char[] content) throws IOException;
128 public abstract JsonParser createParser(char[] content, int offset, int len) throws IOException;
129 public abstract JsonParser createParser(DataInput in) throws IOException;
130 public abstract JsonParser createParser(File f) throws IOException;
131 public abstract JsonParser createParser(InputStream in) throws IOException;
132 public abstract JsonParser createParser(Reader r) throws IOException;
133 public abstract JsonParser createParser(String content) throws IOException;
134 public abstract JsonParser createParser(URL url) throws IOException;
135
136 public abstract JsonParser createNonBlockingByteArrayParser() throws IOException;
137
138 /*
139 /**********************************************************
140 /* Factory methods, generators
141 /**********************************************************
142 */
143
144 public abstract JsonGenerator createGenerator(DataOutput out, JsonEncoding enc) throws IOException;
145 public abstract JsonGenerator createGenerator(DataOutput out) throws IOException;
146 public abstract JsonGenerator createGenerator(File f, JsonEncoding enc) throws IOException;
147 public abstract JsonGenerator createGenerator(OutputStream out) throws IOException;
148 public abstract JsonGenerator createGenerator(OutputStream out, JsonEncoding enc) throws IOException;
149 public abstract JsonGenerator createGenerator(Writer w) throws IOException;
150
151 /*
152 /**********************************************************
153 /* Internal factory methods, other
154 /**********************************************************
155 */
156
157 protected OutputStream _createDataOutputWrapper(DataOutput out) {
158 return new DataOutputAsStream(out);
159 }
160 /**
161 * Helper methods used for constructing an optimal stream for
162 * parsers to use, when input is to be read from an URL.
163 * This helps when reading file content via URL.
164 */
165 protected InputStream _optimizedStreamFromURL(URL url) throws IOException {
166 if ("file".equals(url.getProtocol())) {
167 /* Can not do this if the path refers
168 * to a network drive on windows. This fixes the problem;
169 * might not be needed on all platforms (NFS?), but should not
170 * matter a lot: performance penalty of extra wrapping is more
171 * relevant when accessing local file system.
172 */
173 String host = url.getHost();
174 if (host == null || host.length() == 0) {
175 // [core#48]: Let's try to avoid probs with URL encoded stuff
176 String path = url.getPath();
177 if (path.indexOf('%') < 0) {
178 return new FileInputStream(url.getPath());
179
180 }
181 // otherwise, let's fall through and let URL decoder do its magic
182 }
183 }
184 return url.openStream();
185 }
186 }
1111 {
1212 public abstract <T extends TreeNode> T readTree(JsonParser p) throws IOException, JsonProcessingException;
1313 public abstract void writeTree(JsonGenerator g, TreeNode tree) throws IOException, JsonProcessingException;
14
15 /**
16 * @since 2.10
17 */
18 public TreeNode missingNode() {
19 return null;
20 }
21
22 /**
23 * @since 2.10
24 */
25 public TreeNode nullNode() {
26 return null;
27 }
28
1429 public abstract TreeNode createArrayNode();
1530 public abstract TreeNode createObjectNode();
1631 public abstract JsonParser treeAsTokens(TreeNode node);
2727 *
2828 * @since 2.5
2929 */
30 @SuppressWarnings("deprecation")
3031 protected final static int DERIVED_FEATURES_MASK =
3132 Feature.WRITE_NUMBERS_AS_STRINGS.getMask()
3233 | Feature.ESCAPE_NON_ASCII.getMask()
99100 /**********************************************************
100101 */
101102
103 @SuppressWarnings("deprecation")
102104 protected GeneratorBase(int features, ObjectCodec codec) {
103105 super();
104106 _features = features;
112114 /**
113115 * @since 2.5
114116 */
117 @SuppressWarnings("deprecation")
115118 protected GeneratorBase(int features, ObjectCodec codec, JsonWriteContext ctxt) {
116119 super();
117120 _features = features;
134137
135138 @Override
136139 public void setCurrentValue(Object v) {
137 _writeContext.setCurrentValue(v);
140 if (_writeContext != null) {
141 _writeContext.setCurrentValue(v);
142 }
138143 }
139144
140145 /*
149154
150155 //public JsonGenerator configure(Feature f, boolean state) { }
151156
157 @SuppressWarnings("deprecation")
152158 @Override
153159 public JsonGenerator enable(Feature f) {
154160 final int mask = f.getMask();
168174 return this;
169175 }
170176
177 @SuppressWarnings("deprecation")
171178 @Override
172179 public JsonGenerator disable(Feature f) {
173180 final int mask = f.getMask();
216223 *
217224 * @since 2.7
218225 */
226 @SuppressWarnings("deprecation")
219227 protected void _checkStdFeatureChanges(int newFeatureFlags, int changedFeatures)
220228 {
221229 if ((changedFeatures & DERIVED_FEATURES_MASK) == 0) {
283291 public void writeStartObject(Object forValue) throws IOException
284292 {
285293 writeStartObject();
286 if ((_writeContext != null) && (forValue != null)) {
287 _writeContext.setCurrentValue(forValue);
288 }
289 setCurrentValue(forValue);
294 if (forValue != null) {
295 setCurrentValue(forValue);
296 }
290297 }
291298
292299 /*
55 import java.util.Arrays;
66
77 import com.fasterxml.jackson.core.*;
8 import com.fasterxml.jackson.core.JsonParser.Feature;
89 import com.fasterxml.jackson.core.io.IOContext;
910 import com.fasterxml.jackson.core.io.NumberInput;
1011 import com.fasterxml.jackson.core.json.DupDetector;
844845 } else {
845846 // 16-Oct-2018, tatu: Need to catch "too big" early due to [jackson-core#488]
846847 if ((expType == NR_INT) || (expType == NR_LONG)) {
847 _reportTooLongInt(expType, numStr);
848 _reportTooLongIntegral(expType, numStr);
848849 }
849850 if ((expType == NR_DOUBLE) || (expType == NR_FLOAT)) {
850851 _numberDouble = NumberInput.parseDouble(numStr);
862863 }
863864
864865 // @since 2.9.8
865 protected void _reportTooLongInt(int expType, String rawNum) throws IOException
866 {
867 final String numDesc = _longIntegerDesc(rawNum);
868 _reportError("Numeric value (%s) out of range of %s", numDesc,
869 (expType == NR_LONG) ? "long" : "int");
866 protected void _reportTooLongIntegral(int expType, String rawNum) throws IOException
867 {
868 if (expType == NR_INT) {
869 reportOverflowInt(rawNum);
870 } else {
871 reportOverflowLong(rawNum);
872 }
870873 }
871874
872875 /*
882885 // Let's verify it's lossless conversion by simple roundtrip
883886 int result = (int) _numberLong;
884887 if (((long) result) != _numberLong) {
885 _reportError("Numeric value ("+getText()+") out of range of int");
888 reportOverflowInt(getText(), currentToken());
886889 }
887890 _numberInt = result;
888891 } else if ((_numTypesValid & NR_BIGINT) != 0) {
10141017 (char) actCh, expCh, ctxt.typeDesc(), ctxt.getStartLocation(_getSourceReference())));
10151018 }
10161019
1020 @SuppressWarnings("deprecation")
1021 protected char _handleUnrecognizedCharacterEscape(char ch) throws JsonProcessingException {
1022 // as per [JACKSON-300]
1023 if (isEnabled(Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER)) {
1024 return ch;
1025 }
1026 // and [JACKSON-548]
1027 if (ch == '\'' && isEnabled(Feature.ALLOW_SINGLE_QUOTES)) {
1028 return ch;
1029 }
1030 _reportError("Unrecognized character escape "+_getCharDesc(ch));
1031 return ch;
1032 }
1033
1034 /**
1035 * Method called to report a problem with unquoted control character.
1036 * Note: it is possible to suppress some instances of
1037 * exception by enabling {@link Feature#ALLOW_UNQUOTED_CONTROL_CHARS}.
1038 */
1039 @SuppressWarnings("deprecation")
1040 protected void _throwUnquotedSpace(int i, String ctxtDesc) throws JsonParseException {
1041 // JACKSON-208; possible to allow unquoted control chars:
1042 if (!isEnabled(Feature.ALLOW_UNQUOTED_CONTROL_CHARS) || i > INT_SPACE) {
1043 char c = (char) i;
1044 String msg = "Illegal unquoted character ("+_getCharDesc(c)+"): has to be escaped using backslash to be included in "+ctxtDesc;
1045 _reportError(msg);
1046 }
1047 }
1048
1049 /**
1050 * @return Description to use as "valid tokens" in an exception message about
1051 * invalid (unrecognized) JSON token: called when parser finds something that
1052 * looks like unquoted textual token
1053 *
1054 * @since 2.10
1055 */
1056 protected String _validJsonTokenList() throws IOException {
1057 return _validJsonValueList();
1058 }
1059
1060 /**
1061 * @return Description to use as "valid JSON values" in an exception message about
1062 * invalid (unrecognized) JSON value: called when parser finds something that
1063 * does not look like a value or separator.
1064 *
1065 * @since 2.10
1066 */
1067 @SuppressWarnings("deprecation")
1068 protected String _validJsonValueList() throws IOException {
1069 if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) {
1070 return "(JSON String, Number (or 'NaN'/'INF'/'+INF'), Array, Object or token 'null', 'true' or 'false')";
1071 }
1072 return "(JSON String, Number, Array, Object or token 'null', 'true' or 'false')";
1073 }
1074
10171075 /*
10181076 /**********************************************************
10191077 /* Base64 handling support
44 import java.math.BigInteger;
55
66 import com.fasterxml.jackson.core.*;
7 import com.fasterxml.jackson.core.JsonParser.Feature;
7 import com.fasterxml.jackson.core.exc.InputCoercionException;
88 import com.fasterxml.jackson.core.io.JsonEOFException;
99 import com.fasterxml.jackson.core.io.NumberInput;
1010 import com.fasterxml.jackson.core.util.ByteArrayBuilder;
129129 * @since 2.9
130130 */
131131 protected final static int MAX_ERROR_TOKEN_LENGTH = 256;
132
132
133133 /*
134134 /**********************************************************
135135 /* Minimal generally useful state
540540 _reportError(msg);
541541 }
542542
543 /**
544 * Method called to throw an exception for input token that looks like a number
545 * based on first character(s), but is not valid according to rules of format.
546 * In case of JSON this also includes invalid forms like positive sign and
547 * leading zeroes.
548 */
543549 protected void reportInvalidNumber(String msg) throws JsonParseException {
544550 _reportError("Invalid numeric value: "+msg);
545551 }
546552
553 /**
554 * Method called to throw an exception for integral (not floating point) input
555 * token with value outside of Java signed 32-bit range when requested as {@link int}.
556 * Result will be {@link InputCoercionException} being thrown.
557 */
547558 protected void reportOverflowInt() throws IOException {
548 _reportError(String.format("Numeric value (%s) out of range of int (%d - %s)",
549 _longIntegerDesc(getText()), Integer.MIN_VALUE, Integer.MAX_VALUE));
550 }
551
559 reportOverflowInt(getText());
560 }
561
562 // @since 2.10
563 protected void reportOverflowInt(String numDesc) throws IOException {
564 reportOverflowInt(numDesc, JsonToken.VALUE_NUMBER_INT);
565 }
566
567 // @since 2.10
568 protected void reportOverflowInt(String numDesc, JsonToken inputType) throws IOException {
569 _reportInputCoercion(String.format("Numeric value (%s) out of range of int (%d - %s)",
570 _longIntegerDesc(numDesc), Integer.MIN_VALUE, Integer.MAX_VALUE),
571 inputType, Integer.TYPE);
572 }
573
574 /**
575 * Method called to throw an exception for integral (not floating point) input
576 * token with value outside of Java signed 64-bit range when requested as {@link long}.
577 * Result will be {@link InputCoercionException} being thrown.
578 */
552579 protected void reportOverflowLong() throws IOException {
553 _reportError(String.format("Numeric value (%s) out of range of long (%d - %s)",
554 _longIntegerDesc(getText()), Long.MIN_VALUE, Long.MAX_VALUE));
580 reportOverflowLong(getText());
581 }
582
583 // @since 2.10
584 protected void reportOverflowLong(String numDesc) throws IOException {
585 reportOverflowLong(numDesc, JsonToken.VALUE_NUMBER_INT);
586 }
587
588 // @since 2.10
589 protected void reportOverflowLong(String numDesc, JsonToken inputType) throws IOException {
590 _reportInputCoercion(String.format("Numeric value (%s) out of range of long (%d - %s)",
591 _longIntegerDesc(numDesc), Long.MIN_VALUE, Long.MAX_VALUE),
592 inputType, Long.TYPE);
593 }
594
595 /**
596 * @since 2.10
597 */
598 protected void _reportInputCoercion(String msg, JsonToken inputType, Class<?> targetType)
599 throws InputCoercionException {
600 throw new InputCoercionException(this, msg, inputType, targetType);
555601 }
556602
557603 // @since 2.9.8
643689 _reportError(msg);
644690 }
645691
646 /**
647 * Method called to report a problem with unquoted control character.
648 * Note: starting with version 1.4, it is possible to suppress
649 * exception by enabling {@link Feature#ALLOW_UNQUOTED_CONTROL_CHARS}.
650 */
651 protected void _throwUnquotedSpace(int i, String ctxtDesc) throws JsonParseException {
652 // JACKSON-208; possible to allow unquoted control chars:
653 if (!isEnabled(Feature.ALLOW_UNQUOTED_CONTROL_CHARS) || i > INT_SPACE) {
654 char c = (char) i;
655 String msg = "Illegal unquoted character ("+_getCharDesc(c)+"): has to be escaped using backslash to be included in "+ctxtDesc;
656 _reportError(msg);
657 }
658 }
659
660 protected char _handleUnrecognizedCharacterEscape(char ch) throws JsonProcessingException {
661 // as per [JACKSON-300]
662 if (isEnabled(Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER)) {
663 return ch;
664 }
665 // and [JACKSON-548]
666 if (ch == '\'' && isEnabled(Feature.ALLOW_SINGLE_QUOTES)) {
667 return ch;
668 }
669 _reportError("Unrecognized character escape "+_getCharDesc(ch));
670 return ch;
671 }
672
673692 /*
674693 /**********************************************************
675694 /* Error reporting, generic
0 package com.fasterxml.jackson.core.exc;
1
2 import com.fasterxml.jackson.core.*;
3 import com.fasterxml.jackson.core.util.RequestPayload;
4
5 /**
6 * Exception type for read-side problems that are not direct decoding ("parsing")
7 * problems (those would be reported as {@link com.fasterxml.jackson.core.JsonParseException}s),
8 * but rather result from failed attempts to convert specific Java value out of valid
9 * but incompatible input value. One example is numeric coercions where target number type's
10 * range does not allow mapping of too large/too small input value.
11 *
12 * @since 2.10
13 */
14 public class InputCoercionException extends StreamReadException {
15 private static final long serialVersionUID = 1L;
16
17 /**
18 * Input token that represents input value that failed to coerce.
19 */
20 protected final JsonToken _inputType;
21
22 /**
23 * Target type that input value failed to coerce to.
24 */
25 protected final Class<?> _targetType;
26
27 /**
28 * Constructor that uses current parsing location as location, and
29 * sets processor (accessible via {@link #getProcessor()}) to
30 * specified parser.
31 */
32 public InputCoercionException(JsonParser p, String msg,
33 JsonToken inputType, Class<?> targetType) {
34 super(p, msg);
35 _inputType = inputType;
36 _targetType = targetType;
37 }
38
39 /**
40 * Fluent method that may be used to assign originating {@link JsonParser},
41 * to be accessed using {@link #getProcessor()}.
42 *<p>
43 * NOTE: `this` instance is modified and no new instance is constructed.
44 */
45 @Override
46 public InputCoercionException withParser(JsonParser p) {
47 _processor = p;
48 return this;
49 }
50
51 @Override
52 public InputCoercionException withRequestPayload(RequestPayload p) {
53 _requestPayload = p;
54 return this;
55 }
56
57 /**
58 * Accessor for getting information about input type (in form of token, giving "shape"
59 * of input) for which coercion failed.
60 */
61 public JsonToken getInputType() {
62 return _inputType;
63 }
64
65 /**
66 * Accessor for getting information about target type (in form of Java {@link java.lang.Class})
67 * for which coercion failed.
68 */
69 public Class<?> getTargetType() {
70 return _targetType;
71 }
72 }
0 package com.fasterxml.jackson.core.exc;
1
2 import com.fasterxml.jackson.core.*;
3 import com.fasterxml.jackson.core.util.RequestPayload;
4
5 /**
6 * Intermediate base class for all read-side streaming processing problems, including
7 * parsing and input value coercion problems.
8 *
9 * @since 2.10
10 */
11 public abstract class StreamReadException
12 extends JsonProcessingException
13 {
14 final static long serialVersionUID = 1L;
15
16 protected transient JsonParser _processor;
17
18 /**
19 * Optional payload that can be assigned to pass along for error reporting
20 * or handling purposes. Core streaming parser implementations DO NOT
21 * initialize this; it is up to using applications and frameworks to
22 * populate it.
23 */
24 protected RequestPayload _requestPayload;
25
26 public StreamReadException(JsonParser p, String msg) {
27 super(msg, (p == null) ? null : p.getCurrentLocation());
28 _processor = p;
29 }
30
31 public StreamReadException(JsonParser p, String msg, Throwable root) {
32 super(msg, (p == null) ? null : p.getCurrentLocation(), root);
33 _processor = p;
34 }
35
36 public StreamReadException(JsonParser p, String msg, JsonLocation loc) {
37 super(msg, loc, null);
38 _processor = p;
39 }
40
41 protected StreamReadException(String msg, JsonLocation loc, Throwable rootCause) {
42 super(msg);
43 if (rootCause != null) {
44 initCause(rootCause);
45 }
46 _location = loc;
47 }
48
49 /**
50 * Fluent method that may be used to assign originating {@link JsonParser},
51 * to be accessed using {@link #getProcessor()}.
52 *<p>
53 * NOTE: `this` instance is modified and no new instance is constructed.
54 */
55 public abstract StreamReadException withParser(JsonParser p);
56
57 /**
58 * Fluent method that may be used to assign payload to this exception,
59 * to let recipient access it for diagnostics purposes.
60 *<p>
61 * NOTE: `this` instance is modified and no new instance is constructed.
62 */
63 public abstract StreamReadException withRequestPayload(RequestPayload p);
64
65 @Override
66 public JsonParser getProcessor() {
67 return _processor;
68 }
69
70 /**
71 * Method that may be called to find payload that was being parsed, if
72 * one was specified for parser that threw this Exception.
73 *
74 * @return request body, if payload was specified; `null` otherwise
75 */
76 public RequestPayload getRequestPayload() {
77 return _requestPayload;
78 }
79
80 /**
81 * The method returns the String representation of the request payload if
82 * one was specified for parser that threw this Exception.
83 *
84 * @return request body as String, if payload was specified; `null` otherwise
85 */
86 public String getRequestPayloadAsString() {
87 return (_requestPayload != null) ? _requestPayload.toString() : null;
88 }
89
90 /**
91 * Overriding the getMessage() to include the request body
92 */
93 @Override
94 public String getMessage() {
95 String msg = super.getMessage();
96 if (_requestPayload != null) {
97 msg += "\nRequest payload : " + _requestPayload.toString();
98 }
99 return msg;
100 }
101 }
0 /**
1 * Package for some of {@link com.fasterxml.jackson.core.JsonProcessingException}
2 * subtypes contained by streaming API.
3 */
4 package com.fasterxml.jackson.core.exc;
160160 // 04-Mar-2011, tatu: Used to use "-(i + 1)", replaced with constant
161161 table[i] = CharacterEscapes.ESCAPE_STANDARD;
162162 }
163 /* Others (and some within that range too) have explicit shorter
164 * sequences
165 */
163 // Others (and some within that range too) have explicit shorter sequences
166164 table['"'] = '"';
167165 table['\\'] = '\\';
168166 // Escaping of slash is optional, so let's not add it
209207 */
210208 public static int[] get7BitOutputEscapes() { return sOutputEscapes128; }
211209
210 /**
211 * Alternative to {@link #get7BitOutputEscapes()} when a non-standard quote character
212 * is used.
213 *
214 * @since 2.10
215 */
216 public static int[] get7BitOutputEscapes(int quoteChar) {
217 if (quoteChar == '"') {
218 return sOutputEscapes128;
219 }
220 return AltEscapes.instance.escapesFor(quoteChar);
221 }
222
212223 public static int charToHex(int ch)
213224 {
214225 return (ch > 127) ? -1 : sHexValues[ch];
254265 public static byte[] copyHexBytes() {
255266 return (byte[]) HB.clone();
256267 }
268
269 // @since 2.10
270 private static class AltEscapes {
271 public final static AltEscapes instance = new AltEscapes();
272
273 private int[][] _altEscapes = new int[128][];
274
275 public int[] escapesFor(int quoteChar) {
276 int[] esc = _altEscapes[quoteChar];
277 if (esc == null) {
278 esc = Arrays.copyOf(sOutputEscapes128, 128);
279 // Only add escape setting if character does not already have it
280 if (esc[quoteChar] == 0) {
281 esc[quoteChar] = CharacterEscapes.ESCAPE_STANDARD;
282 }
283 _altEscapes[quoteChar] = esc;
284 }
285 return esc;
286 }
287 }
257288 }
258289
00 package com.fasterxml.jackson.core.io;
11
2 import com.fasterxml.jackson.core.util.BufferRecyclers;
2 import java.util.Arrays;
3
34 import com.fasterxml.jackson.core.util.ByteArrayBuilder;
45 import com.fasterxml.jackson.core.util.TextBuffer;
56
1011 * Note that methods in here are somewhat optimized, but not ridiculously so.
1112 * Reason is that conversion method results are expected to be cached so that
1213 * these methods will not be hot spots during normal operation.
13 *<p>
14 * NOTE: starting with 2.9.3, access to most functionality should go through
15 * {@link BufferRecyclers} and NOT directly through this class.
1614 */
1715 public final class JsonStringEncoder
1816 {
17 /*
18 /**********************************************************************
19 /* Constants
20 /**********************************************************************
21 */
22
1923 private final static char[] HC = CharTypes.copyHexChars();
2024
2125 private final static byte[] HB = CharTypes.copyHexBytes();
2529 private final static int SURR2_FIRST = 0xDC00;
2630 private final static int SURR2_LAST = 0xDFFF;
2731
28 // private final static int INT_BACKSLASH = '\\';
29 // private final static int INT_U = 'u';
30 // private final static int INT_0 = '0';
31
32 /**
33 * Lazily constructed text buffer used to produce JSON encoded Strings
34 * as characters (without UTF-8 encoding)
35 */
36 protected TextBuffer _text;
37
38 /**
39 * Lazily-constructed builder used for UTF-8 encoding of text values
40 * (quoted and unquoted)
41 */
42 protected ByteArrayBuilder _bytes;
32 private final static int INITIAL_CHAR_BUFFER_SIZE = 120;
33 private final static int INITIAL_BYTE_BUFFER_SIZE = 200;
34
35 /*
36 /**********************************************************************
37 /* Construction, instance access
38 /**********************************************************************
39 */
40
41 // Since 2.10 we have stateless singleton and NO fancy ThreadLocal/SofRef caching!!!
42 private final static JsonStringEncoder instance = new JsonStringEncoder();
4343
44 /**
45 * Temporary buffer used for composing quote/escape sequences
46 */
47 protected final char[] _qbuf;
48
49 /*
50 /**********************************************************
51 /* Construction, instance access
52 /**********************************************************
53 */
54
55 public JsonStringEncoder() {
56 _qbuf = new char[6];
57 _qbuf[0] = '\\';
58 _qbuf[2] = '0';
59 _qbuf[3] = '0';
60 }
61
44 public JsonStringEncoder() { }
45
6246 /**
6347 * Factory method for getting an instance; this is either recycled per-thread instance,
6448 * or a newly constructed one.
65 *
66 * @deprecated Since 2.9.2 use {@link BufferRecyclers#getJsonStringEncoder()} instead
67 */
68 @Deprecated
49 */
6950 public static JsonStringEncoder getInstance() {
70 return BufferRecyclers.getJsonStringEncoder();
51 return instance;
7152 }
7253
7354 /*
74 /**********************************************************
55 /**********************************************************************
7556 /* Public API
76 /**********************************************************
57 /**********************************************************************
7758 */
7859
7960 /**
8263 */
8364 public char[] quoteAsString(String input)
8465 {
85 TextBuffer textBuffer = _text;
66 char[] outputBuffer = new char[INITIAL_CHAR_BUFFER_SIZE];
67 final int[] escCodes = CharTypes.get7BitOutputEscapes();
68 final int escCodeCount = escCodes.length;
69 int inPtr = 0;
70 final int inputLen = input.length();
71 TextBuffer textBuffer = null;
72 int outPtr = 0;
73 char[] qbuf = null;
74
75 outer:
76 while (inPtr < inputLen) {
77 tight_loop:
78 while (true) {
79 char c = input.charAt(inPtr);
80 if (c < escCodeCount && escCodes[c] != 0) {
81 break tight_loop;
82 }
83 if (outPtr >= outputBuffer.length) {
84 if (textBuffer == null) {
85 textBuffer = TextBuffer.fromInitial(outputBuffer);
86 }
87 outputBuffer = textBuffer.finishCurrentSegment();
88 outPtr = 0;
89 }
90 outputBuffer[outPtr++] = c;
91 if (++inPtr >= inputLen) {
92 break outer;
93 }
94 }
95 // something to escape; 2 or 6-char variant?
96 if (qbuf == null) {
97 qbuf = _qbuf();
98 }
99 char d = input.charAt(inPtr++);
100 int escCode = escCodes[d];
101 int length = (escCode < 0)
102 ? _appendNumeric(d, qbuf)
103 : _appendNamed(escCode, qbuf);
104 ;
105 if ((outPtr + length) > outputBuffer.length) {
106 int first = outputBuffer.length - outPtr;
107 if (first > 0) {
108 System.arraycopy(qbuf, 0, outputBuffer, outPtr, first);
109 }
110 if (textBuffer == null) {
111 textBuffer = TextBuffer.fromInitial(outputBuffer);
112 }
113 outputBuffer = textBuffer.finishCurrentSegment();
114 int second = length - first;
115 System.arraycopy(qbuf, first, outputBuffer, 0, second);
116 outPtr = second;
117 } else {
118 System.arraycopy(qbuf, 0, outputBuffer, outPtr, length);
119 outPtr += length;
120 }
121 }
122
86123 if (textBuffer == null) {
87 // no allocator; can add if we must, shouldn't need to
88 _text = textBuffer = new TextBuffer(null);
89 }
90 char[] outputBuffer = textBuffer.emptyAndGetCurrentSegment();
124 return Arrays.copyOfRange(outputBuffer, 0, outPtr);
125 }
126 textBuffer.setCurrentLength(outPtr);
127 return textBuffer.contentsAsArray();
128 }
129
130 /**
131 * Overloaded variant of {@link #quoteAsString(String)}.
132 *
133 * @since 2.10
134 */
135 public char[] quoteAsString(CharSequence input)
136 {
137 // 15-Aug-2019, tatu: Optimize common case as JIT can't get rid of overhead otherwise
138 if (input instanceof String) {
139 return quoteAsString((String) input);
140 }
141
142 TextBuffer textBuffer = null;
143
144 char[] outputBuffer = new char[INITIAL_CHAR_BUFFER_SIZE];
91145 final int[] escCodes = CharTypes.get7BitOutputEscapes();
92146 final int escCodeCount = escCodes.length;
93147 int inPtr = 0;
94148 final int inputLen = input.length();
95149 int outPtr = 0;
150 char[] qbuf = null;
96151
97152 outer:
98153 while (inPtr < inputLen) {
103158 break tight_loop;
104159 }
105160 if (outPtr >= outputBuffer.length) {
161 if (textBuffer == null) {
162 textBuffer = TextBuffer.fromInitial(outputBuffer);
163 }
106164 outputBuffer = textBuffer.finishCurrentSegment();
107165 outPtr = 0;
108166 }
112170 }
113171 }
114172 // something to escape; 2 or 6-char variant?
173 if (qbuf == null) {
174 qbuf = _qbuf();
175 }
115176 char d = input.charAt(inPtr++);
116177 int escCode = escCodes[d];
117178 int length = (escCode < 0)
118 ? _appendNumeric(d, _qbuf)
119 : _appendNamed(escCode, _qbuf);
179 ? _appendNumeric(d, qbuf)
180 : _appendNamed(escCode, qbuf);
120181 ;
121182 if ((outPtr + length) > outputBuffer.length) {
122183 int first = outputBuffer.length - outPtr;
123184 if (first > 0) {
124 System.arraycopy(_qbuf, 0, outputBuffer, outPtr, first);
185 System.arraycopy(qbuf, 0, outputBuffer, outPtr, first);
186 }
187 if (textBuffer == null) {
188 textBuffer = TextBuffer.fromInitial(outputBuffer);
125189 }
126190 outputBuffer = textBuffer.finishCurrentSegment();
127191 int second = length - first;
128 System.arraycopy(_qbuf, first, outputBuffer, 0, second);
192 System.arraycopy(qbuf, first, outputBuffer, 0, second);
129193 outPtr = second;
130194 } else {
131 System.arraycopy(_qbuf, 0, outputBuffer, outPtr, length);
195 System.arraycopy(qbuf, 0, outputBuffer, outPtr, length);
132196 outPtr += length;
133197 }
198 }
199
200 if (textBuffer == null) {
201 return Arrays.copyOfRange(outputBuffer, 0, outPtr);
134202 }
135203 textBuffer.setCurrentLength(outPtr);
136204 return textBuffer.contentsAsArray();
149217 final int escCodeCount = escCodes.length;
150218 int inPtr = 0;
151219 final int inputLen = input.length();
220 char[] qbuf = null;
152221
153222 outer:
154223 while (inPtr < inputLen) {
164233 }
165234 }
166235 // something to escape; 2 or 6-char variant?
236 if (qbuf == null) {
237 qbuf = _qbuf();
238 }
167239 char d = input.charAt(inPtr++);
168240 int escCode = escCodes[d];
169241 int length = (escCode < 0)
170 ? _appendNumeric(d, _qbuf)
171 : _appendNamed(escCode, _qbuf);
172 ;
173 output.append(_qbuf, 0, length);
242 ? _appendNumeric(d, qbuf)
243 : _appendNamed(escCode, qbuf);
244 output.append(qbuf, 0, length);
174245 }
175246 }
176247
181252 @SuppressWarnings("resource")
182253 public byte[] quoteAsUTF8(String text)
183254 {
184 ByteArrayBuilder bb = _bytes;
185 if (bb == null) {
186 // no allocator; can add if we must, shouldn't need to
187 _bytes = bb = new ByteArrayBuilder(null);
188 }
189255 int inputPtr = 0;
190256 int inputEnd = text.length();
191257 int outputPtr = 0;
192 byte[] outputBuffer = bb.resetAndGetFirstSegment();
258 byte[] outputBuffer = new byte[INITIAL_BYTE_BUFFER_SIZE];
259 ByteArrayBuilder bb = null;
193260
194261 main:
195262 while (inputPtr < inputEnd) {
202269 break inner_loop;
203270 }
204271 if (outputPtr >= outputBuffer.length) {
272 if (bb == null) {
273 bb = ByteArrayBuilder.fromInitial(outputBuffer, outputPtr);
274 }
205275 outputBuffer = bb.finishCurrentSegment();
206276 outputPtr = 0;
207277 }
209279 if (++inputPtr >= inputEnd) {
210280 break main;
211281 }
212 }
282 }
283 if (bb == null) {
284 bb = ByteArrayBuilder.fromInitial(outputBuffer, outputPtr);
285 }
213286 if (outputPtr >= outputBuffer.length) {
214287 outputBuffer = bb.finishCurrentSegment();
215288 outputPtr = 0;
268341 }
269342 outputBuffer[outputPtr++] = (byte) ch;
270343 }
271 return _bytes.completeAndCoalesce(outputPtr);
272 }
273
344 if (bb == null) {
345 return Arrays.copyOfRange(outputBuffer, 0, outputPtr);
346 }
347 return bb.completeAndCoalesce(outputPtr);
348 }
349
274350 /**
275351 * Will encode given String as UTF-8 (without any quoting), return
276352 * resulting byte array.
278354 @SuppressWarnings("resource")
279355 public byte[] encodeAsUTF8(String text)
280356 {
281 ByteArrayBuilder byteBuilder = _bytes;
282 if (byteBuilder == null) {
283 // no allocator; can add if we must, shouldn't need to
284 _bytes = byteBuilder = new ByteArrayBuilder(null);
285 }
286357 int inputPtr = 0;
287358 int inputEnd = text.length();
288359 int outputPtr = 0;
289 byte[] outputBuffer = byteBuilder.resetAndGetFirstSegment();
360 byte[] outputBuffer = new byte[INITIAL_BYTE_BUFFER_SIZE];
290361 int outputEnd = outputBuffer.length;
291
362 ByteArrayBuilder bb = null;
363
292364 main_loop:
293365 while (inputPtr < inputEnd) {
294366 int c = text.charAt(inputPtr++);
296368 // first tight loop for ascii
297369 while (c <= 0x7F) {
298370 if (outputPtr >= outputEnd) {
299 outputBuffer = byteBuilder.finishCurrentSegment();
371 if (bb == null) {
372 bb = ByteArrayBuilder.fromInitial(outputBuffer, outputPtr);
373 }
374 outputBuffer = bb.finishCurrentSegment();
300375 outputEnd = outputBuffer.length;
301376 outputPtr = 0;
302377 }
308383 }
309384
310385 // then multi-byte...
386 if (bb == null) {
387 bb = ByteArrayBuilder.fromInitial(outputBuffer, outputPtr);
388 }
311389 if (outputPtr >= outputEnd) {
312 outputBuffer = byteBuilder.finishCurrentSegment();
390 outputBuffer = bb.finishCurrentSegment();
313391 outputEnd = outputBuffer.length;
314392 outputPtr = 0;
315393 }
320398 if (c < SURR1_FIRST || c > SURR2_LAST) { // nope
321399 outputBuffer[outputPtr++] = (byte) (0xe0 | (c >> 12));
322400 if (outputPtr >= outputEnd) {
323 outputBuffer = byteBuilder.finishCurrentSegment();
401 outputBuffer = bb.finishCurrentSegment();
324402 outputEnd = outputBuffer.length;
325403 outputPtr = 0;
326404 }
339417 }
340418 outputBuffer[outputPtr++] = (byte) (0xf0 | (c >> 18));
341419 if (outputPtr >= outputEnd) {
342 outputBuffer = byteBuilder.finishCurrentSegment();
420 outputBuffer = bb.finishCurrentSegment();
343421 outputEnd = outputBuffer.length;
344422 outputPtr = 0;
345423 }
346424 outputBuffer[outputPtr++] = (byte) (0x80 | ((c >> 12) & 0x3f));
347425 if (outputPtr >= outputEnd) {
348 outputBuffer = byteBuilder.finishCurrentSegment();
426 outputBuffer = bb.finishCurrentSegment();
349427 outputEnd = outputBuffer.length;
350428 outputPtr = 0;
351429 }
353431 }
354432 }
355433 if (outputPtr >= outputEnd) {
356 outputBuffer = byteBuilder.finishCurrentSegment();
434 outputBuffer = bb.finishCurrentSegment();
357435 outputEnd = outputBuffer.length;
358436 outputPtr = 0;
359437 }
360438 outputBuffer[outputPtr++] = (byte) (0x80 | (c & 0x3f));
361439 }
362 return _bytes.completeAndCoalesce(outputPtr);
363 }
364
440 if (bb == null) {
441 return Arrays.copyOfRange(outputBuffer, 0, outputPtr);
442 }
443 return bb.completeAndCoalesce(outputPtr);
444 }
445
365446 /*
366 /**********************************************************
447 /**********************************************************************
367448 /* Internal methods
368 /**********************************************************
369 */
449 /**********************************************************************
450 */
451
452 private char[] _qbuf() {
453 char[] qbuf = new char[6];
454 qbuf[0] = '\\';
455 qbuf[2] = '0';
456 qbuf[3] = '0';
457 return qbuf;
458 }
370459
371460 private int _appendNumeric(int value, char[] qbuf) {
372461 qbuf[1] = 'u';
2626 */
2727 public static int parseInt(char[] ch, int off, int len)
2828 {
29 int num = ch[off] - '0';
30
31 if (len > 4) {
32 num = (num * 10) + (ch[++off] - '0');
33 num = (num * 10) + (ch[++off] - '0');
34 num = (num * 10) + (ch[++off] - '0');
35 num = (num * 10) + (ch[++off] - '0');
36 len -= 4;
37 if (len > 4) {
38 num = (num * 10) + (ch[++off] - '0');
39 num = (num * 10) + (ch[++off] - '0');
40 num = (num * 10) + (ch[++off] - '0');
41 num = (num * 10) + (ch[++off] - '0');
42 return num;
43 }
44 }
45 if (len > 1) {
46 num = (num * 10) + (ch[++off] - '0');
47 if (len > 2) {
48 num = (num * 10) + (ch[++off] - '0');
49 if (len > 3) {
50 num = (num * 10) + (ch[++off] - '0');
51 }
52 }
29 int num = ch[off + len - 1] - '0';
30
31 switch(len) {
32 case 9:
33 num += (ch[off++] - '0') * 100000000;
34 case 8:
35 num += (ch[off++] - '0') * 10000000;
36 case 7:
37 num += (ch[off++] - '0') * 1000000;
38 case 6:
39 num += (ch[off++] - '0') * 100000;
40 case 5:
41 num += (ch[off++] - '0') * 10000;
42 case 4:
43 num += (ch[off++] - '0') * 1000;
44 case 3:
45 num += (ch[off++] - '0') * 100;
46 case 2:
47 num += (ch[off] - '0') * 10;
5348 }
5449 return num;
5550 }
266266
267267 /*
268268 /**********************************************************
269 /* Other convenience methods
270 /**********************************************************
271 */
272
273 /**
274 * Helper method to verify whether given {@code double} value is finite
275 * (regular rational number} or not (NaN or Infinity).
276 *
277 * @return True if number is NOT finite (is Infinity or NaN); false otherwise
278 *
279 * Since 2.10
280 */
281 public static boolean notFinite(double value) {
282 // before Java 8 need separate checks
283 return Double.isNaN(value) || Double.isInfinite(value);
284 }
285
286 /**
287 * Helper method to verify whether given {@code float} value is finite
288 * (regular rational number} or not (NaN or Infinity).
289 *
290 * @return True if number is NOT finite (is Infinity or NaN); false otherwise
291 *
292 * Since 2.10
293 */
294 public static boolean notFinite(float value) {
295 // before Java 8 need separate checks
296 return Float.isNaN(value) || Float.isInfinite(value);
297 }
298
299 /*
300 /**********************************************************
269301 /* Internal helper methods
270302 /**********************************************************
271303 */
33 import java.nio.ByteBuffer;
44
55 import com.fasterxml.jackson.core.SerializableString;
6 import com.fasterxml.jackson.core.util.BufferRecyclers;
76
87 /**
98 * String token that can lazily serialize String contained and then reuse that
1918 {
2019 private static final long serialVersionUID = 1L;
2120
21 private static final JsonStringEncoder JSON_ENCODER = JsonStringEncoder.getInstance();
22
2223 protected final String _value;
2324
2425 /* 13-Dec-2010, tatu: Whether use volatile or not is actually an important
9394 */
9495 @Override
9596 public final int charLength() { return _value.length(); }
96
97
98 /**
99 * Accessor for accessing value that has been quoted (escaped) using JSON
100 * quoting rules (using backslash-prefixed codes) into a char array.
101 */
97102 @Override
98103 public final char[] asQuotedChars() {
99104 char[] result = _quotedChars;
100105 if (result == null) {
101 result = BufferRecyclers.quoteAsJsonText(_value);
102 _quotedChars = result;
106 _quotedChars = result = JSON_ENCODER.quoteAsString(_value);
103107 }
104108 return result;
105109 }
106110
107111 /**
108 * Accessor for accessing value that has been quoted using JSON
109 * quoting rules, and encoded using UTF-8 encoding.
112 * Accessor for accessing value that has been quoted (escaped) using JSON
113 * quoting rules (using backslash-prefixed codes), and encoded using
114 * UTF-8 encoding into a byte array.
115 */
116 @Override
117 public final byte[] asQuotedUTF8() {
118 byte[] result = _quotedUTF8Ref;
119 if (result == null) {
120 _quotedUTF8Ref = result = JSON_ENCODER.quoteAsUTF8(_value);
121 }
122 return result;
123 }
124
125 /**
126 * Accessor for accessing value as is (without JSON quoting (ecaping))
127 * encoded as UTF-8 byte array.
110128 */
111129 @Override
112130 public final byte[] asUnquotedUTF8() {
113131 byte[] result = _unquotedUTF8Ref;
114132 if (result == null) {
115 result = BufferRecyclers.encodeAsUTF8(_value);
116 _unquotedUTF8Ref = result;
133 _unquotedUTF8Ref = result = JSON_ENCODER.encodeAsUTF8(_value);
117134 }
118135 return result;
119136 }
120137
121 /**
122 * Accessor for accessing value as is (without JSON quoting)
123 * encoded using UTF-8 encoding.
124 */
125 @Override
126 public final byte[] asQuotedUTF8() {
127 byte[] result = _quotedUTF8Ref;
128 if (result == null) {
129 result = BufferRecyclers.quoteAsJsonUTF8(_value);
130 _quotedUTF8Ref = result;
131 }
132 return result;
133 }
134
135138 /*
136139 /**********************************************************
137140 /* Additional 2.0 methods for appending/writing contents
138141 /**********************************************************
139142 */
140
141 @Override
142 public int appendQuotedUTF8(byte[] buffer, int offset) {
143 byte[] result = _quotedUTF8Ref;
144 if (result == null) {
145 result = BufferRecyclers.quoteAsJsonUTF8(_value);
146 _quotedUTF8Ref = result;
147 }
148 final int length = result.length;
149 if ((offset + length) > buffer.length) {
150 return -1;
151 }
152 System.arraycopy(result, 0, buffer, offset, length);
153 return length;
154 }
155143
156144 @Override
157145 public int appendQuoted(char[] buffer, int offset) {
158146 char[] result = _quotedChars;
159147 if (result == null) {
160 result = BufferRecyclers.quoteAsJsonText(_value);
161 _quotedChars = result;
148 _quotedChars = result = JSON_ENCODER.quoteAsString(_value);
162149 }
163150 final int length = result.length;
164151 if ((offset + length) > buffer.length) {
169156 }
170157
171158 @Override
172 public int appendUnquotedUTF8(byte[] buffer, int offset) {
173 byte[] result = _unquotedUTF8Ref;
174 if (result == null) {
175 result = BufferRecyclers.encodeAsUTF8(_value);
176 _unquotedUTF8Ref = result;
159 public int appendQuotedUTF8(byte[] buffer, int offset) {
160 byte[] result = _quotedUTF8Ref;
161 if (result == null) {
162 _quotedUTF8Ref = result = JSON_ENCODER.quoteAsUTF8(_value);
177163 }
178164 final int length = result.length;
179165 if ((offset + length) > buffer.length) {
195181 }
196182
197183 @Override
184 public int appendUnquotedUTF8(byte[] buffer, int offset) {
185 byte[] result = _unquotedUTF8Ref;
186 if (result == null) {
187 _unquotedUTF8Ref = result = JSON_ENCODER.encodeAsUTF8(_value);
188 }
189 final int length = result.length;
190 if ((offset + length) > buffer.length) {
191 return -1;
192 }
193 System.arraycopy(result, 0, buffer, offset, length);
194 return length;
195 }
196
197 @Override
198198 public int writeQuotedUTF8(OutputStream out) throws IOException {
199199 byte[] result = _quotedUTF8Ref;
200200 if (result == null) {
201 result = BufferRecyclers.quoteAsJsonUTF8(_value);
202 _quotedUTF8Ref = result;
201 _quotedUTF8Ref = result = JSON_ENCODER.quoteAsUTF8(_value);
203202 }
204203 final int length = result.length;
205204 out.write(result, 0, length);
210209 public int writeUnquotedUTF8(OutputStream out) throws IOException {
211210 byte[] result = _unquotedUTF8Ref;
212211 if (result == null) {
213 result = BufferRecyclers.encodeAsUTF8(_value);
214 _unquotedUTF8Ref = result;
212 _unquotedUTF8Ref = result = JSON_ENCODER.encodeAsUTF8(_value);
215213 }
216214 final int length = result.length;
217215 out.write(result, 0, length);
222220 public int putQuotedUTF8(ByteBuffer buffer) {
223221 byte[] result = _quotedUTF8Ref;
224222 if (result == null) {
225 result = BufferRecyclers.quoteAsJsonUTF8(_value);
226 _quotedUTF8Ref = result;
223 _quotedUTF8Ref = result = JSON_ENCODER.quoteAsUTF8(_value);
227224 }
228225 final int length = result.length;
229226 if (length > buffer.remaining()) {
237234 public int putUnquotedUTF8(ByteBuffer buffer) {
238235 byte[] result = _unquotedUTF8Ref;
239236 if (result == null) {
240 result = BufferRecyclers.encodeAsUTF8(_value);
241 _unquotedUTF8Ref = result;
237 _unquotedUTF8Ref = result = JSON_ENCODER.encodeAsUTF8(_value);
242238 }
243239 final int length = result.length;
244240 if (length > buffer.remaining()) {
248244 return length;
249245 }
250246
251
252247 /*
253248 /**********************************************************
254249 /* Standard method overrides
242242 ByteQuadsCanonicalizer rootByteSymbols, CharsToNameCanonicalizer rootCharSymbols,
243243 int factoryFeatures) throws IOException
244244 {
245 int prevInputPtr = _inputPtr;
245246 JsonEncoding enc = detectEncoding();
247 int bytesProcessed = _inputPtr - prevInputPtr;
246248
247249 if (enc == JsonEncoding.UTF8) {
248250 /* and without canonicalization, byte-based approach is not performant; just use std UTF-8 reader
251253 if (JsonFactory.Feature.CANONICALIZE_FIELD_NAMES.enabledIn(factoryFeatures)) {
252254 ByteQuadsCanonicalizer can = rootByteSymbols.makeChild(factoryFeatures);
253255 return new UTF8StreamJsonParser(_context, parserFeatures, _in, codec, can,
254 _inputBuffer, _inputPtr, _inputEnd, _bufferRecyclable);
256 _inputBuffer, _inputPtr, _inputEnd, bytesProcessed, _bufferRecyclable);
255257 }
256258 }
257259 return new ReaderBasedJsonParser(_context, parserFeatures, constructReader(), codec,
9797 /**********************************************************
9898 */
9999
100 @SuppressWarnings("deprecation")
100101 public JsonGeneratorImpl(IOContext ctxt, int features, ObjectCodec codec)
101102 {
102103 super(features, codec);
125126 /**********************************************************
126127 */
127128
129 @SuppressWarnings("deprecation")
128130 @Override
129131 public JsonGenerator enable(Feature f) {
130132 super.enable(f);
134136 return this;
135137 }
136138
139 @SuppressWarnings("deprecation")
137140 @Override
138141 public JsonGenerator disable(Feature f) {
139142 super.disable(f);
143146 return this;
144147 }
145148
149 @SuppressWarnings("deprecation")
146150 @Override
147151 protected void _checkStdFeatureChanges(int newFeatureFlags, int changedFeatures) {
148152 super._checkStdFeatureChanges(newFeatureFlags, changedFeatures);
0 package com.fasterxml.jackson.core.json;
1
2 import com.fasterxml.jackson.core.*;
3
4 /**
5 * Token reader (parser) features specific to JSON backend.
6 * Eventual replacement for JSON-specific {@link com.fasterxml.jackson.core.JsonParser.Feature}s.
7 *
8 * @since 2.10
9 */
10 public enum JsonReadFeature
11 implements FormatFeature
12 {
13 // // // Support for non-standard data format constructs: comments
14
15 /**
16 * Feature that determines whether parser will allow use
17 * of Java/C/C++ style comments (both '/'+'*' and
18 * '//' varieties) within parsed content or not.
19 *<p>
20 * Since JSON specification does not mention comments as legal
21 * construct,
22 * this is a non-standard feature; however, in the wild
23 * this is extensively used. As such, feature is
24 * <b>disabled by default</b> for parsers and must be
25 * explicitly enabled.
26 */
27 ALLOW_JAVA_COMMENTS(false, JsonParser.Feature.ALLOW_COMMENTS),
28
29 /**
30 * Feature that determines whether parser will allow use
31 * of YAML comments, ones starting with '#' and continuing
32 * until the end of the line. This commenting style is common
33 * with scripting languages as well.
34 *<p>
35 * Since JSON specification does not mention comments as legal
36 * construct,
37 * this is a non-standard feature. As such, feature is
38 * <b>disabled by default</b> for parsers and must be
39 * explicitly enabled.
40 */
41 ALLOW_YAML_COMMENTS(false, JsonParser.Feature.ALLOW_YAML_COMMENTS),
42
43 // // // Support for non-standard data format constructs: quoting/escaping
44
45 /**
46 * Feature that determines whether parser will allow use
47 * of single quotes (apostrophe, character '\'') for
48 * quoting Strings (names and String values). If so,
49 * this is in addition to other acceptable markers.
50 * but not by JSON specification).
51 *<p>
52 * Since JSON specification requires use of double quotes for
53 * field names,
54 * this is a non-standard feature, and as such disabled by default.
55 */
56 ALLOW_SINGLE_QUOTES(false, JsonParser.Feature.ALLOW_SINGLE_QUOTES),
57
58 /**
59 * Feature that determines whether parser will allow use
60 * of unquoted field names (which is allowed by Javascript,
61 * but not by JSON specification).
62 *<p>
63 * Since JSON specification requires use of double quotes for
64 * field names,
65 * this is a non-standard feature, and as such disabled by default.
66 */
67 ALLOW_UNQUOTED_FIELD_NAMES(false, JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES),
68
69 /**
70 * Feature that determines whether parser will allow
71 * JSON Strings to contain unescaped control characters
72 * (ASCII characters with value less than 32, including
73 * tab and line feed characters) or not.
74 * If feature is set false, an exception is thrown if such a
75 * character is encountered.
76 *<p>
77 * Since JSON specification requires quoting for all control characters,
78 * this is a non-standard feature, and as such disabled by default.
79 */
80 @SuppressWarnings("deprecation")
81 ALLOW_UNESCAPED_CONTROL_CHARS(false, JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS),
82
83 /**
84 * Feature that can be enabled to accept quoting of all character
85 * using backslash quoting mechanism: if not enabled, only characters
86 * that are explicitly listed by JSON specification can be thus
87 * escaped (see JSON spec for small list of these characters)
88 *<p>
89 * Since JSON specification requires quoting for all control characters,
90 * this is a non-standard feature, and as such disabled by default.
91 */
92 @SuppressWarnings("deprecation")
93 ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER(false, JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER),
94
95 // // // Support for non-standard data format constructs: number representations
96
97 /**
98 * Feature that determines whether parser will allow
99 * JSON integral numbers to start with additional (ignorable)
100 * zeroes (like: 000001). If enabled, no exception is thrown, and extra
101 * nulls are silently ignored (and not included in textual representation
102 * exposed via {@link JsonParser#getText}).
103 *<p>
104 * Since JSON specification does not allow leading zeroes,
105 * this is a non-standard feature, and as such disabled by default.
106 */
107 @SuppressWarnings("deprecation")
108 ALLOW_LEADING_ZEROS_FOR_NUMBERS(false, JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS),
109
110 /**
111 * Feature that allows parser to recognize set of
112 * "Not-a-Number" (NaN) tokens as legal floating number
113 * values (similar to how many other data formats and
114 * programming language source code allows it).
115 * Specific subset contains values that
116 * <a href="http://www.w3.org/TR/xmlschema-2/">XML Schema</a>
117 * (see section 3.2.4.1, Lexical Representation)
118 * allows (tokens are quoted contents, not including quotes):
119 *<ul>
120 * <li>"INF" (for positive infinity), as well as alias of "Infinity"
121 * <li>"-INF" (for negative infinity), alias "-Infinity"
122 * <li>"NaN" (for other not-a-numbers, like result of division by zero)
123 *</ul>
124 *<p>
125 * Since JSON specification does not allow use of such values,
126 * this is a non-standard feature, and as such disabled by default.
127 */
128 @SuppressWarnings("deprecation")
129 ALLOW_NON_NUMERIC_NUMBERS(false, JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS),
130
131 // // // Support for non-standard data format constructs: array/value separators
132
133 /**
134 * Feature allows the support for "missing" values in a JSON array: missing
135 * value meaning sequence of two commas, without value in-between but only
136 * optional white space.
137 * Enabling this feature will expose "missing" values as {@link JsonToken#VALUE_NULL}
138 * tokens, which typically become Java nulls in arrays and {@link java.util.Collection}
139 * in data-binding.
140 * <p>
141 * For example, enabling this feature will represent a JSON array <code>["value1",,"value3",]</code>
142 * as <code>["value1", null, "value3", null]</code>
143 * <p>
144 * Since the JSON specification does not allow missing values this is a non-compliant JSON
145 * feature and is disabled by default.
146 */
147 @SuppressWarnings("deprecation")
148 ALLOW_MISSING_VALUES(false, JsonParser.Feature.ALLOW_MISSING_VALUES),
149
150 /**
151 * Feature that determines whether {@link JsonParser} will allow for a single trailing
152 * comma following the final value (in an Array) or member (in an Object). These commas
153 * will simply be ignored.
154 * <p>
155 * For example, when this feature is enabled, <code>[true,true,]</code> is equivalent to
156 * <code>[true, true]</code> and <code>{"a": true,}</code> is equivalent to
157 * <code>{"a": true}</code>.
158 * <p>
159 * When combined with <code>ALLOW_MISSING_VALUES</code>, this feature takes priority, and
160 * the final trailing comma in an array declaration does not imply a missing
161 * (<code>null</code>) value. For example, when both <code>ALLOW_MISSING_VALUES</code>
162 * and <code>ALLOW_TRAILING_COMMA</code> are enabled, <code>[true,true,]</code> is
163 * equivalent to <code>[true, true]</code>, and <code>[true,true,,]</code> is equivalent to
164 * <code>[true, true, null]</code>.
165 * <p>
166 * Since the JSON specification does not permit trailing commas, this is a non-standard
167 * feature, and as such disabled by default.
168 */
169 @SuppressWarnings("deprecation")
170 ALLOW_TRAILING_COMMA(false, JsonParser.Feature.ALLOW_TRAILING_COMMA),
171 ;
172
173 final private boolean _defaultState;
174 final private int _mask;
175
176 /**
177 * For backwards compatibility we may need to map to one of existing {@link JsonParser.Feature}s;
178 * if so, this is the feature to enable/disable.
179 */
180 final private JsonParser.Feature _mappedFeature;
181
182 /**
183 * Method that calculates bit set (flags) of all features that
184 * are enabled by default.
185 */
186 public static int collectDefaults()
187 {
188 int flags = 0;
189 for (JsonReadFeature f : values()) {
190 if (f.enabledByDefault()) {
191 flags |= f.getMask();
192 }
193 }
194 return flags;
195 }
196
197 private JsonReadFeature(boolean defaultState,
198 JsonParser.Feature mapTo) {
199 _defaultState = defaultState;
200 _mask = (1 << ordinal());
201 _mappedFeature = mapTo;
202 }
203
204 @Override
205 public boolean enabledByDefault() { return _defaultState; }
206 @Override
207 public int getMask() { return _mask; }
208 @Override
209 public boolean enabledIn(int flags) { return (flags & _mask) != 0; }
210
211 public JsonParser.Feature mappedFeature() { return _mappedFeature; }
212 }
2828
2929 /*
3030 /**********************************************************
31 /* Simple instance reuse slots; speed up things
32 /* a bit (10-15%) for docs with lots of small
33 /* arrays/objects
31 /* Simple instance reuse slots; speed up things a bit (10-15%)
32 /* for docs with lots of small arrays/objects
3433 /**********************************************************
3534 */
3635
7170 _parent = parent;
7271 _dups = dups;
7372 _index = -1;
73 }
74
75 /* @since 2.10 */
76 protected JsonWriteContext(int type, JsonWriteContext parent, DupDetector dups,
77 Object currValue) {
78 super();
79 _type = type;
80 _parent = parent;
81 _dups = dups;
82 _index = -1;
83 _currentValue = currValue;
7484 }
7585
7686 protected JsonWriteContext reset(int type) {
8393 return this;
8494 }
8595
96 /* @since 2.10 */
97 protected JsonWriteContext reset(int type, Object currValue) {
98 _type = type;
99 _index = -1;
100 _currentName = null;
101 _gotName = false;
102 _currentValue = currValue;
103 if (_dups != null) { _dups.reset(); }
104 return this;
105 }
106
86107 public JsonWriteContext withDupDetector(DupDetector dups) {
87108 _dups = dups;
88109 return this;
117138 public JsonWriteContext createChildArrayContext() {
118139 JsonWriteContext ctxt = _child;
119140 if (ctxt == null) {
120 _child = ctxt = new JsonWriteContext(TYPE_ARRAY, this, (_dups == null) ? null : _dups.child());
141 _child = ctxt = new JsonWriteContext(TYPE_ARRAY, this,
142 (_dups == null) ? null : _dups.child());
121143 return ctxt;
122144 }
123145 return ctxt.reset(TYPE_ARRAY);
124146 }
125147
148 /* @since 2.10 */
149 public JsonWriteContext createChildArrayContext(Object currValue) {
150 JsonWriteContext ctxt = _child;
151 if (ctxt == null) {
152 _child = ctxt = new JsonWriteContext(TYPE_ARRAY, this,
153 (_dups == null) ? null : _dups.child(), currValue);
154 return ctxt;
155 }
156 return ctxt.reset(TYPE_ARRAY, currValue);
157 }
158
126159 public JsonWriteContext createChildObjectContext() {
127160 JsonWriteContext ctxt = _child;
128161 if (ctxt == null) {
129 _child = ctxt = new JsonWriteContext(TYPE_OBJECT, this, (_dups == null) ? null : _dups.child());
162 _child = ctxt = new JsonWriteContext(TYPE_OBJECT, this,
163 (_dups == null) ? null : _dups.child());
130164 return ctxt;
131165 }
132166 return ctxt.reset(TYPE_OBJECT);
167 }
168
169 /* @since 2.10 */
170 public JsonWriteContext createChildObjectContext(Object currValue) {
171 JsonWriteContext ctxt = _child;
172 if (ctxt == null) {
173 _child = ctxt = new JsonWriteContext(TYPE_OBJECT, this,
174 (_dups == null) ? null : _dups.child(), currValue);
175 return ctxt;
176 }
177 return ctxt.reset(TYPE_OBJECT, currValue);
133178 }
134179
135180 @Override public final JsonWriteContext getParent() { return _parent; }
152197 // could also clear the current name, but seems cheap enough to leave?
153198 return _parent;
154199 }
155
200
156201 public DupDetector getDupDetector() {
157202 return _dups;
158203 }
0 package com.fasterxml.jackson.core.json;
1
2 import com.fasterxml.jackson.core.*;
3
4 /**
5 * Token writer features specific to JSON backend.
6 *
7 * @since 2.10
8 */
9 public enum JsonWriteFeature
10 implements FormatFeature
11 {
12 // // // Support for non-standard data format constructs: comments
13
14 // // Quoting/ecsaping-related features
15
16 /**
17 * Feature that determines whether JSON Object field names are
18 * quoted using double-quotes, as specified by JSON specification
19 * or not. Ability to disable quoting was added to support use
20 * cases where they are not usually expected, which most commonly
21 * occurs when used straight from Javascript.
22 *<p>
23 * Feature is enabled by default (since it is required by JSON specification).
24 */
25 @SuppressWarnings("deprecation")
26 QUOTE_FIELD_NAMES(true, JsonGenerator.Feature.QUOTE_FIELD_NAMES),
27
28 /**
29 * Feature that determines whether "NaN" ("not a number", that is, not
30 * real number) float/double values are output as JSON strings.
31 * The values checked are Double.Nan,
32 * Double.POSITIVE_INFINITY and Double.NEGATIVE_INIFINTY (and
33 * associated Float values).
34 * If feature is disabled, these numbers are still output using
35 * associated literal values, resulting in non-conforming
36 * output.
37 *<p>
38 * Feature is enabled by default.
39 */
40 @SuppressWarnings("deprecation")
41 WRITE_NAN_AS_STRINGS(true, JsonGenerator.Feature.QUOTE_NON_NUMERIC_NUMBERS),
42
43 /**
44 * Feature that forces all regular number values to be written as JSON Strings,
45 * instead of as JSON Numbers.
46 * Default state is 'false', meaning that Java numbers are to
47 * be serialized using basic numeric representation but
48 * if enabled all such numeric values are instead written out as
49 * JSON Strings instead.
50 *<p>
51 * One use case is to avoid problems with Javascript limitations:
52 * since Javascript standard specifies that all number handling
53 * should be done using 64-bit IEEE 754 floating point values,
54 * result being that some 64-bit integer values can not be
55 * accurately represent (as mantissa is only 51 bit wide).
56 *<p>
57 * Feature is disabled by default.
58 */
59 @SuppressWarnings("deprecation")
60 WRITE_NUMBERS_AS_STRINGS(false, JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS),
61
62 /**
63 * Feature that specifies that all characters beyond 7-bit ASCII
64 * range (i.e. code points of 128 and above) need to be output
65 * using format-specific escapes (for JSON, backslash escapes),
66 * if format uses escaping mechanisms (which is generally true
67 * for textual formats but not for binary formats).
68 *<p>
69 * Note that this setting may not necessarily make sense for all
70 * data formats (for example, binary formats typically do not use
71 * any escaping mechanisms; and some textual formats do not have
72 * general-purpose escaping); if so, settings is simply ignored.
73 * Put another way, effects of this feature are data-format specific.
74 *<p>
75 * Feature is disabled by default.
76 */
77 @SuppressWarnings("deprecation")
78 ESCAPE_NON_ASCII(false, JsonGenerator.Feature.ESCAPE_NON_ASCII),
79
80 //23-Nov-2015, tatu: for [core#223], if and when it gets implemented
81 /*
82 * Feature that specifies handling of UTF-8 content that contains
83 * characters beyond BMP (Basic Multilingual Plane), which are
84 * represented in UCS-2 (Java internal character encoding) as two
85 * "surrogate" characters. If feature is enabled, these surrogate
86 * pairs are separately escaped using backslash escapes; if disabled,
87 * native output (4-byte UTF-8 sequence, or, with char-backed output
88 * targets, writing of surrogates as is which is typically converted
89 * by {@link java.io.Writer} into 4-byte UTF-8 sequence eventually)
90 * is used.
91 *<p>
92 * Note that the original JSON specification suggests use of escaping;
93 * but that this is not correct from standard UTF-8 handling perspective.
94 * Because of two competing goals, this feature was added to allow either
95 * behavior to be used, but defaulting to UTF-8 specification compliant
96 * mode.
97 *<p>
98 * Feature is disabled by default.
99 */
100 // ESCAPE_UTF8_SURROGATES(false, JsonGenerator.Feature.ESCAPE_UTF8_SURROGATES),
101
102 ;
103
104 final private boolean _defaultState;
105 final private int _mask;
106
107 /**
108 * For backwards compatibility we may need to map to one of existing {@link JsonGenerator.Feature}s;
109 * if so, this is the feature to enable/disable.
110 */
111 final private JsonGenerator.Feature _mappedFeature;
112
113 /**
114 * Method that calculates bit set (flags) of all features that
115 * are enabled by default.
116 */
117 public static int collectDefaults()
118 {
119 int flags = 0;
120 for (JsonWriteFeature f : values()) {
121 if (f.enabledByDefault()) {
122 flags |= f.getMask();
123 }
124 }
125 return flags;
126 }
127
128 private JsonWriteFeature(boolean defaultState,
129 JsonGenerator.Feature mapTo) {
130 _defaultState = defaultState;
131 _mask = (1 << ordinal());
132 _mappedFeature = mapTo;
133 }
134
135 @Override
136 public boolean enabledByDefault() { return _defaultState; }
137 @Override
138 public int getMask() { return _mask; }
139 @Override
140 public boolean enabledIn(int flags) { return (flags & _mask) != 0; }
141
142 public JsonGenerator.Feature mappedFeature() { return _mappedFeature; }
143 }
1818 public class ReaderBasedJsonParser // final in 2.3, earlier
1919 extends ParserBase
2020 {
21 protected final static int FEAT_MASK_TRAILING_COMMA = Feature.ALLOW_TRAILING_COMMA.getMask();
21 @SuppressWarnings("deprecation")
22 private final static int FEAT_MASK_TRAILING_COMMA = Feature.ALLOW_TRAILING_COMMA.getMask();
23
24 @SuppressWarnings("deprecation")
25 private final static int FEAT_MASK_LEADING_ZEROS = Feature.ALLOW_NUMERIC_LEADING_ZEROS.getMask();
26
27 @SuppressWarnings("deprecation")
28 private final static int FEAT_MASK_NON_NUM_NUMBERS = Feature.ALLOW_NON_NUMERIC_NUMBERS.getMask();
29
30 @SuppressWarnings("deprecation")
31 private final static int FEAT_MASK_ALLOW_MISSING = Feature.ALLOW_MISSING_VALUES.getMask();
32 private final static int FEAT_MASK_ALLOW_SINGLE_QUOTES = Feature.ALLOW_SINGLE_QUOTES.getMask();
33 private final static int FEAT_MASK_ALLOW_UNQUOTED_NAMES = Feature.ALLOW_UNQUOTED_FIELD_NAMES.getMask();
34
35 private final static int FEAT_MASK_ALLOW_JAVA_COMMENTS = Feature.ALLOW_COMMENTS.getMask();
36 private final static int FEAT_MASK_ALLOW_YAML_COMMENTS = Feature.ALLOW_YAML_COMMENTS.getMask();
2237
2338 // Latin1 encoding is not supported, but we do use 8-bit subset for
2439 // pre-processing task, to simplify first pass, keep it fast.
11241139 */
11251140 case ',':
11261141 case ']':
1127 if(isEnabled(Feature.ALLOW_MISSING_VALUES)) {
1128 _inputPtr--;
1129 return (_currToken = JsonToken.VALUE_NULL);
1130 }
1142 if ((_features & FEAT_MASK_ALLOW_MISSING) != 0) {
1143 --_inputPtr;
1144 return (_currToken = JsonToken.VALUE_NULL);
1145 }
11311146 }
11321147 return (_currToken = _handleOddValue(i));
11331148 }
1134
11351149 // note: identical to one in UTF8StreamJsonParser
11361150 @Override
11371151 public final String nextTextValue() throws IOException
15841598 if (ch < '0' || ch > '9') {
15851599 return '0';
15861600 }
1587 if (!isEnabled(Feature.ALLOW_NUMERIC_LEADING_ZEROS)) {
1601 if ((_features & FEAT_MASK_LEADING_ZEROS) == 0) {
15881602 reportInvalidNumber("Leading zeroes not allowed");
15891603 }
15901604 // if so, just need to skip either all zeroes (if followed by number); or all but one (if non-number)
16201634 if (ch == 'N') {
16211635 String match = negative ? "-INF" :"+INF";
16221636 _matchToken(match, 3);
1623 if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) {
1637 if ((_features & FEAT_MASK_NON_NUM_NUMBERS) != 0) {
16241638 return resetAsNaN(match, negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY);
16251639 }
16261640 _reportError("Non-standard token '"+match+"': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow");
16271641 } else if (ch == 'n') {
16281642 String match = negative ? "-Infinity" :"+Infinity";
16291643 _matchToken(match, 3);
1630 if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) {
1644 if ((_features & FEAT_MASK_NON_NUM_NUMBERS) != 0) {
16311645 return resetAsNaN(match, negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY);
16321646 }
16331647 _reportError("Non-standard token '"+match+"': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow");
17581772 protected String _handleOddName(int i) throws IOException
17591773 {
17601774 // [JACKSON-173]: allow single quotes
1761 if (i == '\'' && isEnabled(Feature.ALLOW_SINGLE_QUOTES)) {
1775 if (i == '\'' && (_features & FEAT_MASK_ALLOW_SINGLE_QUOTES) != 0) {
17621776 return _parseAposName();
17631777 }
17641778 // [JACKSON-69]: allow unquoted names if feature enabled:
1765 if (!isEnabled(Feature.ALLOW_UNQUOTED_FIELD_NAMES)) {
1779 if ((_features & FEAT_MASK_ALLOW_UNQUOTED_NAMES) == 0) {
17661780 _reportUnexpectedChar(i, "was expecting double-quote to start field name");
17671781 }
17681782 final int[] codes = CharTypes.getInputCodeLatin1JsNames();
18521866 * Also, no separation to fast/slow parsing; we'll just do
18531867 * one regular (~= slowish) parsing, to keep code simple
18541868 */
1855 if (isEnabled(Feature.ALLOW_SINGLE_QUOTES)) {
1869 if ((_features & FEAT_MASK_ALLOW_SINGLE_QUOTES) != 0) {
18561870 return _handleApos();
18571871 }
18581872 break;
18661880 }
18671881 // fall through
18681882 case ',':
1869 if (isEnabled(Feature.ALLOW_MISSING_VALUES)) {
1883 if ((_features & FEAT_MASK_ALLOW_MISSING) != 0) {
18701884 --_inputPtr;
18711885 return JsonToken.VALUE_NULL;
18721886 }
18731887 break;
18741888 case 'N':
18751889 _matchToken("NaN", 1);
1876 if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) {
1890 if ((_features & FEAT_MASK_NON_NUM_NUMBERS) != 0) {
18771891 return resetAsNaN("NaN", Double.NaN);
18781892 }
18791893 _reportError("Non-standard token 'NaN': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow");
18801894 break;
18811895 case 'I':
18821896 _matchToken("Infinity", 1);
1883 if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) {
1897 if ((_features & FEAT_MASK_NON_NUM_NUMBERS) != 0) {
18841898 return resetAsNaN("Infinity", Double.POSITIVE_INFINITY);
18851899 }
18861900 _reportError("Non-standard token 'Infinity': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow");
18951909 }
18961910 // [core#77] Try to decode most likely token
18971911 if (Character.isJavaIdentifierStart(i)) {
1898 _reportInvalidToken(""+((char) i), "('true', 'false' or 'null')");
1912 _reportInvalidToken(""+((char) i), _validJsonTokenList());
18991913 }
19001914 // but if it doesn't look like a token:
1901 _reportUnexpectedChar(i, "expected a valid value (number, String, array, object, 'true', 'false' or 'null')");
1915 _reportUnexpectedChar(i, "expected a valid value "+_validJsonValueList());
19021916 return null;
19031917 }
19041918
24162430
24172431 private void _skipComment() throws IOException
24182432 {
2419 if (!isEnabled(Feature.ALLOW_COMMENTS)) {
2433 if ((_features & FEAT_MASK_ALLOW_JAVA_COMMENTS) == 0) {
24202434 _reportUnexpectedChar('/', "maybe a (non-standard) comment? (not recognized as one since Feature 'ALLOW_COMMENTS' not enabled for parser)");
24212435 }
24222436 // First: check which comment (if either) it is:
24662480
24672481 private boolean _skipYAMLComment() throws IOException
24682482 {
2469 if (!isEnabled(Feature.ALLOW_YAML_COMMENTS)) {
2483 if ((_features & FEAT_MASK_ALLOW_YAML_COMMENTS) == 0) {
24702484 return false;
24712485 }
24722486 _skipLine();
28272841 */
28282842
28292843 protected void _reportInvalidToken(String matchedPart) throws IOException {
2830 _reportInvalidToken(matchedPart, "'null', 'true', 'false' or NaN");
2844 _reportInvalidToken(matchedPart, _validJsonTokenList());
28312845 }
28322846
28332847 protected void _reportInvalidToken(String matchedPart, String msg) throws IOException
3636 {
3737 final static byte BYTE_LF = (byte) '\n';
3838
39 @SuppressWarnings("deprecation")
40 private final static int FEAT_MASK_TRAILING_COMMA = Feature.ALLOW_TRAILING_COMMA.getMask();
41 @SuppressWarnings("deprecation")
42 private final static int FEAT_MASK_LEADING_ZEROS = Feature.ALLOW_NUMERIC_LEADING_ZEROS.getMask();
43 @SuppressWarnings("deprecation")
44 private final static int FEAT_MASK_NON_NUM_NUMBERS = Feature.ALLOW_NON_NUMERIC_NUMBERS.getMask();
45 @SuppressWarnings("deprecation")
46 private final static int FEAT_MASK_ALLOW_MISSING = Feature.ALLOW_MISSING_VALUES.getMask();
47 private final static int FEAT_MASK_ALLOW_SINGLE_QUOTES = Feature.ALLOW_SINGLE_QUOTES.getMask();
48 private final static int FEAT_MASK_ALLOW_UNQUOTED_NAMES = Feature.ALLOW_UNQUOTED_FIELD_NAMES.getMask();
49 private final static int FEAT_MASK_ALLOW_JAVA_COMMENTS = Feature.ALLOW_COMMENTS.getMask();
50 private final static int FEAT_MASK_ALLOW_YAML_COMMENTS = Feature.ALLOW_YAML_COMMENTS.getMask();
51
3952 // This is the main input-code lookup table, fetched eagerly
4053 private final static int[] _icUTF8 = CharTypes.getInputCodeUtf8();
4154
604617 i = _skipWS();
605618
606619 // Was that a trailing comma?
607 if (Feature.ALLOW_TRAILING_COMMA.enabledIn(_features)) {
620 if ((_features & FEAT_MASK_TRAILING_COMMA) != 0) {
608621 if (i == INT_RBRACKET || i == INT_RCURLY) {
609622 _closeScope(i);
610623 return _currToken;
786799 i = _skipWS();
787800
788801 // Was that a trailing comma?
789 if (Feature.ALLOW_TRAILING_COMMA.enabledIn(_features)) {
802 if ((_features & FEAT_MASK_TRAILING_COMMA) != 0) {
790803 if (i == INT_RBRACKET || i == INT_RCURLY) {
791804 _closeScope(i);
792805 return null;
10781091 return ch;
10791092 }
10801093 // we may want to allow leading zeroes them, after all...
1081 if (!isEnabled(Feature.ALLOW_NUMERIC_LEADING_ZEROS)) {
1094 if ((_features & FEAT_MASK_LEADING_ZEROS) == 0) {
10821095 reportInvalidNumber("Leading zeroes not allowed");
10831096 }
10841097 // if so, just need to skip either all zeroes (if followed by number); or all but one (if non-number)
14941507 */
14951508 protected String _handleOddName(int ch) throws IOException
14961509 {
1497 if (ch == '\'' && isEnabled(Feature.ALLOW_SINGLE_QUOTES)) {
1510 if (ch == '\'' && (_features & FEAT_MASK_ALLOW_SINGLE_QUOTES) != 0) {
14981511 return _parseAposName();
14991512 }
1500 if (!isEnabled(Feature.ALLOW_UNQUOTED_FIELD_NAMES)) {
1513 if ((_features & FEAT_MASK_ALLOW_UNQUOTED_NAMES) == 0) {
15011514 char c = (char) _decodeCharForError(ch);
15021515 _reportUnexpectedChar(c, "was expecting double-quote to start field name");
15031516 }
20132026 /* !!! TODO: 08-May-2016, tatu: To support `Feature.ALLOW_MISSING_VALUES` would
20142027 * need handling here...
20152028 */
2016 if (isEnabled(Feature.ALLOW_MISSING_VALUES)) {
2029 if ((_features & FEAT_MASK_ALLOW_MISSING) != 0) {
20172030 // _inputPtr--;
20182031 _nextByte = c;
20192032 return JsonToken.VALUE_NULL;
20242037 // been handled earlier
20252038 _reportUnexpectedChar(c, "expected a value");
20262039 case '\'':
2027 if (isEnabled(Feature.ALLOW_SINGLE_QUOTES)) {
2040 if ((_features & FEAT_MASK_ALLOW_SINGLE_QUOTES) != 0) {
20282041 return _handleApos();
20292042 }
20302043 break;
20312044 case 'N':
20322045 _matchToken("NaN", 1);
2033 if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) {
2046 if ((_features & FEAT_MASK_NON_NUM_NUMBERS) != 0) {
20342047 return resetAsNaN("NaN", Double.NaN);
20352048 }
20362049 _reportError("Non-standard token 'NaN': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow");
20372050 break;
20382051 case 'I':
20392052 _matchToken("Infinity", 1);
2040 if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) {
2053 if ((_features & FEAT_MASK_NON_NUM_NUMBERS) != 0) {
20412054 return resetAsNaN("Infinity", Double.POSITIVE_INFINITY);
20422055 }
20432056 _reportError("Non-standard token 'Infinity': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow");
20472060 }
20482061 // [core#77] Try to decode most likely token
20492062 if (Character.isJavaIdentifierStart(c)) {
2050 _reportInvalidToken(c, ""+((char) c), "('true', 'false' or 'null')");
2063 _reportInvalidToken(c, ""+((char) c), _validJsonTokenList());
20512064 }
20522065 // but if it doesn't look like a token:
2053 _reportUnexpectedChar(c, "expected a valid value (number, String, array, object, 'true', 'false' or 'null')");
2066 _reportUnexpectedChar(c, "expected a valid value "+_validJsonValueList());
20542067 return null;
20552068 }
20562069
21452158 break;
21462159 }
21472160 _matchToken(match, 3);
2148 if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) {
2161 if ((_features & FEAT_MASK_NON_NUM_NUMBERS) != 0) {
21492162 return resetAsNaN(match, neg ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY);
21502163 }
21512164 _reportError("Non-standard token '"+match+"': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow");
23632376
23642377 private final void _skipComment() throws IOException
23652378 {
2366 if (!isEnabled(Feature.ALLOW_COMMENTS)) {
2379 if ((_features & FEAT_MASK_ALLOW_JAVA_COMMENTS) == 0) {
23672380 _reportUnexpectedChar('/', "maybe a (non-standard) comment? (not recognized as one since Feature 'ALLOW_COMMENTS' not enabled for parser)");
23682381 }
23692382 int c = _inputData.readUnsignedByte();
24182431
24192432 private final boolean _skipYAMLComment() throws IOException
24202433 {
2421 if (!isEnabled(Feature.ALLOW_YAML_COMMENTS)) {
2434 if ((_features & FEAT_MASK_ALLOW_YAML_COMMENTS) == 0) {
24222435 return false;
24232436 }
24242437 _skipLine();
26592672
26602673 protected void _reportInvalidToken(int ch, String matchedPart) throws IOException
26612674 {
2662 _reportInvalidToken(ch, matchedPart, "'null', 'true', 'false' or NaN");
2675 _reportInvalidToken(ch, matchedPart, _validJsonTokenList());
26632676 }
26642677
26652678 protected void _reportInvalidToken(int ch, String matchedPart, String msg)
5151 *
5252 * @since 2.8
5353 */
54 protected byte _quoteChar = '"'; // TODO: make configurable
55
54 protected byte _quoteChar;
55
5656 /*
5757 /**********************************************************
5858 /* Output buffering
112112 /**********************************************************
113113 */
114114
115 /**
116 * @since 2.10
117 */
118 @SuppressWarnings("deprecation")
115119 public UTF8JsonGenerator(IOContext ctxt, int features, ObjectCodec codec,
116 OutputStream out)
120 OutputStream out, char quoteChar)
117121 {
118122 super(ctxt, features, codec);
119123 _outputStream = out;
124 _quoteChar = (byte) quoteChar;
125 if (quoteChar != '"') { // since 2.10
126 _outputEscapes = CharTypes.get7BitOutputEscapes(quoteChar);
127 }
128
120129 _bufferRecyclable = true;
121130 _outputBuffer = ctxt.allocWriteEncodingBuffer();
122131 _outputEnd = _outputBuffer.length;
134143 setHighestNonEscapedChar(127);
135144 }
136145 }
137
146
147 /**
148 * @since 2.10
149 */
138150 public UTF8JsonGenerator(IOContext ctxt, int features, ObjectCodec codec,
139 OutputStream out,
151 OutputStream out, char quoteChar,
140152 byte[] outputBuffer, int outputOffset, boolean bufferRecyclable)
141153 {
142154
143155 super(ctxt, features, codec);
144156 _outputStream = out;
157 _quoteChar = (byte) quoteChar;
158 if (quoteChar != '"') { // since 2.10
159 _outputEscapes = CharTypes.get7BitOutputEscapes(quoteChar);
160 }
161
145162 _bufferRecyclable = bufferRecyclable;
146163 _outputTail = outputOffset;
147164 _outputBuffer = outputBuffer;
152169 _charBufferLength = _charBuffer.length;
153170 }
154171
172 @Deprecated // since 2.10
173 public UTF8JsonGenerator(IOContext ctxt, int features, ObjectCodec codec,
174 OutputStream out) {
175 this(ctxt, features, codec, out, JsonFactory.DEFAULT_QUOTE_CHAR);
176 }
177
178 @Deprecated // since 2.10
179 public UTF8JsonGenerator(IOContext ctxt, int features, ObjectCodec codec,
180 OutputStream out,
181 byte[] outputBuffer, int outputOffset, boolean bufferRecyclable)
182 {
183 this(ctxt, features, codec, out, JsonFactory.DEFAULT_QUOTE_CHAR,
184 outputBuffer, outputOffset, bufferRecyclable);
185 }
186
155187 /*
156188 /**********************************************************
157189 /* Overridden configuration methods
158190 /**********************************************************
159191 */
160
192
161193 @Override
162194 public Object getOutputTarget() {
163195 return _outputStream;
292324 }
293325 }
294326
327 @Override // since 2.10
328 public void writeStartArray(int size) throws IOException
329 {
330 _verifyValueWrite("start an array");
331 _writeContext = _writeContext.createChildArrayContext();
332 if (_cfgPrettyPrinter != null) {
333 _cfgPrettyPrinter.writeStartArray(this);
334 } else {
335 if (_outputTail >= _outputEnd) {
336 _flushBuffer();
337 }
338 _outputBuffer[_outputTail++] = BYTE_LBRACKET;
339 }
340 }
341
295342 @Override
296343 public final void writeEndArray() throws IOException
297344 {
328375 public void writeStartObject(Object forValue) throws IOException
329376 {
330377 _verifyValueWrite("start an object");
331 JsonWriteContext ctxt = _writeContext.createChildObjectContext();
378 JsonWriteContext ctxt = _writeContext.createChildObjectContext(forValue);
332379 _writeContext = ctxt;
333 if (forValue != null) {
334 ctxt.setCurrentValue(forValue);
335 }
336380 if (_cfgPrettyPrinter != null) {
337381 _cfgPrettyPrinter.writeStartObject(this);
338382 } else {
342386 _outputBuffer[_outputTail++] = '{';
343387 }
344388 }
345
389
346390 @Override
347391 public final void writeEndObject() throws IOException
348392 {
423467 }
424468 _outputBuffer[_outputTail++] = _quoteChar;
425469 }
426 _writeBytes(name.asQuotedUTF8());
470 int len = name.appendQuotedUTF8(_outputBuffer, _outputTail);
471 if (len < 0) {
472 _writeBytes(name.asQuotedUTF8());
473 } else {
474 _outputTail += len;
475 }
427476 if (addQuotes) {
428477 if (_outputTail >= _outputEnd) {
429478 _flushBuffer();
474523
475524 final char[] buf = _charBuffer;
476525
477 //Add leading quote
478 if ((_outputTail + len) >= _outputEnd) {
479 _flushBuffer();
480 }
481 _outputBuffer[_outputTail++] = _quoteChar;
482
483 //read
526 // Add leading quote
527 if (_outputTail >= _outputEnd) {
528 _flushBuffer();
529 }
530 _outputBuffer[_outputTail++] = _quoteChar;
531
532 // read
484533 while (toRead > 0){
485534 int toReadNow = Math.min(toRead, buf.length);
486535 int numRead = reader.read(buf, 0, toReadNow);
495544 toRead -= numRead;
496545 }
497546
498 //Add trailing quote
499 if ((_outputTail + len) >= _outputEnd) {
547 // Add trailing quote
548 if (_outputTail >= _outputEnd) {
500549 _flushBuffer();
501550 }
502551 _outputBuffer[_outputTail++] = _quoteChar;
650699 @Override
651700 public void writeRaw(SerializableString text) throws IOException
652701 {
653 byte[] raw = text.asUnquotedUTF8();
654 if (raw.length > 0) {
655 _writeBytes(raw);
702 int len = text.appendUnquotedUTF8(_outputBuffer, _outputTail);
703 if (len < 0) {
704 _writeBytes(text.asUnquotedUTF8());
705 } else {
706 _outputTail += len;
656707 }
657708 }
658709
660711 @Override
661712 public void writeRawValue(SerializableString text) throws IOException {
662713 _verifyValueWrite(WRITE_RAW);
663 byte[] raw = text.asUnquotedUTF8();
664 if (raw.length > 0) {
665 _writeBytes(raw);
714 int len = text.appendUnquotedUTF8(_outputBuffer, _outputTail);
715 if (len < 0) {
716 _writeBytes(text.asUnquotedUTF8());
717 } else {
718 _outputTail += len;
666719 }
667720 }
668721
9521005 }
9531006 }
9541007
955
1008 @SuppressWarnings("deprecation")
9561009 @Override
9571010 public void writeNumber(double d) throws IOException
9581011 {
9591012 if (_cfgNumbersAsStrings ||
960 (((Double.isNaN(d) || Double.isInfinite(d))
961 && Feature.QUOTE_NON_NUMERIC_NUMBERS.enabledIn(_features)))) {
1013 (NumberOutput.notFinite(d)
1014 && Feature.QUOTE_NON_NUMERIC_NUMBERS.enabledIn(_features))) {
9621015 writeString(String.valueOf(d));
9631016 return;
9641017 }
9671020 writeRaw(String.valueOf(d));
9681021 }
9691022
1023 @SuppressWarnings("deprecation")
9701024 @Override
9711025 public void writeNumber(float f) throws IOException
9721026 {
9731027 if (_cfgNumbersAsStrings ||
974 // [JACKSON-139]
975 (((Float.isNaN(f) || Float.isInfinite(f))
976 && Feature.QUOTE_NON_NUMERIC_NUMBERS.enabledIn(_features)))) {
1028 (NumberOutput.notFinite(f)
1029 && Feature.QUOTE_NON_NUMERIC_NUMBERS.enabledIn(_features))) {
9771030 writeString(String.valueOf(f));
9781031 return;
9791032 }
13061359 }
13071360 _outputTail = outputPtr;
13081361 if (offset < len) {
1309 // [JACKSON-106]
13101362 if (_characterEscapes != null) {
13111363 _writeCustomStringSegment2(cbuf, offset, len);
1312 // [JACKSON-102]
13131364 } else if (_maximumNonEscapedChar == 0) {
13141365 _writeStringSegment2(cbuf, offset, len);
13151366 } else {
1919 {
2020 final static byte BYTE_LF = (byte) '\n';
2121
22 @SuppressWarnings("deprecation")
23 private final static int FEAT_MASK_TRAILING_COMMA = Feature.ALLOW_TRAILING_COMMA.getMask();
24 @SuppressWarnings("deprecation")
25 private final static int FEAT_MASK_LEADING_ZEROS = Feature.ALLOW_NUMERIC_LEADING_ZEROS.getMask();
26 @SuppressWarnings("deprecation")
27 private final static int FEAT_MASK_NON_NUM_NUMBERS = Feature.ALLOW_NON_NUMERIC_NUMBERS.getMask();
28 @SuppressWarnings("deprecation")
29 private final static int FEAT_MASK_ALLOW_MISSING = Feature.ALLOW_MISSING_VALUES.getMask();
30 private final static int FEAT_MASK_ALLOW_SINGLE_QUOTES = Feature.ALLOW_SINGLE_QUOTES.getMask();
31 private final static int FEAT_MASK_ALLOW_UNQUOTED_NAMES = Feature.ALLOW_UNQUOTED_FIELD_NAMES.getMask();
32 private final static int FEAT_MASK_ALLOW_JAVA_COMMENTS = Feature.ALLOW_COMMENTS.getMask();
33 private final static int FEAT_MASK_ALLOW_YAML_COMMENTS = Feature.ALLOW_YAML_COMMENTS.getMask();
34
2235 // This is the main input-code lookup table, fetched eagerly
2336 private final static int[] _icUTF8 = CharTypes.getInputCodeUtf8();
2437
2538 // Latin1 encoding is not supported, but we do use 8-bit subset for
2639 // pre-processing task, to simplify first pass, keep it fast.
2740 protected final static int[] _icLatin1 = CharTypes.getInputCodeLatin1();
28
29 protected final static int FEAT_MASK_TRAILING_COMMA = Feature.ALLOW_TRAILING_COMMA.getMask();
3041
3142 /*
3243 /**********************************************************
125136 /**********************************************************
126137 */
127138
139 /**
140 * @deprecated Since 2.10
141 */
142 @Deprecated
128143 public UTF8StreamJsonParser(IOContext ctxt, int features, InputStream in,
129144 ObjectCodec codec, ByteQuadsCanonicalizer sym,
130145 byte[] inputBuffer, int start, int end,
146 boolean bufferRecyclable)
147 {
148 this(ctxt, features, in, codec, sym,
149 inputBuffer, start, end, 0, bufferRecyclable);
150 }
151
152 public UTF8StreamJsonParser(IOContext ctxt, int features, InputStream in,
153 ObjectCodec codec, ByteQuadsCanonicalizer sym,
154 byte[] inputBuffer, int start, int end, int bytesPreProcessed,
131155 boolean bufferRecyclable)
132156 {
133157 super(ctxt, features);
137161 _inputBuffer = inputBuffer;
138162 _inputPtr = start;
139163 _inputEnd = end;
140 _currInputRowStart = start;
164 _currInputRowStart = start - bytesPreProcessed;
141165 // If we have offset, need to omit that from byte offset, so:
142 _currInputProcessed = -start;
166 _currInputProcessed = -start + bytesPreProcessed;
143167 _bufferRecyclable = bufferRecyclable;
144168 }
145169
14901514 return INT_0;
14911515 }
14921516 // [JACKSON-358]: we may want to allow them, after all...
1493 if (!isEnabled(Feature.ALLOW_NUMERIC_LEADING_ZEROS)) {
1517 if ((_features & FEAT_MASK_LEADING_ZEROS) == 0) {
14941518 reportInvalidNumber("Leading zeroes not allowed");
14951519 }
14961520 // if so, just need to skip either all zeroes (if followed by number); or all but one (if non-number)
19862010 protected String _handleOddName(int ch) throws IOException
19872011 {
19882012 // First: may allow single quotes
1989 if (ch == INT_APOS && isEnabled(Feature.ALLOW_SINGLE_QUOTES)) {
2013 if (ch == INT_APOS && (_features & FEAT_MASK_ALLOW_SINGLE_QUOTES) != 0) {
19902014 return _parseAposName();
19912015 }
19922016 // Allow unquoted names if feature enabled:
1993 if (!isEnabled(Feature.ALLOW_UNQUOTED_FIELD_NAMES)) {
2017 if ((_features & FEAT_MASK_ALLOW_UNQUOTED_NAMES) == 0) {
19942018 char c = (char) _decodeCharForError(ch);
19952019 _reportUnexpectedChar(c, "was expecting double-quote to start field name");
19962020 }
25852609 // 28-Mar-2016: [core#116]: If Feature.ALLOW_MISSING_VALUES is enabled
25862610 // we may allow "missing values", that is, encountering a trailing
25872611 // comma or closing marker where value would be expected
2588 if (isEnabled(Feature.ALLOW_MISSING_VALUES)) {
2612 if ((_features & FEAT_MASK_ALLOW_MISSING) != 0) {
25892613 --_inputPtr;
25902614 return JsonToken.VALUE_NULL;
25912615 }
25952619 // been handled earlier
25962620 _reportUnexpectedChar(c, "expected a value");
25972621 case '\'':
2598 if (isEnabled(Feature.ALLOW_SINGLE_QUOTES)) {
2622 if ((_features & FEAT_MASK_ALLOW_SINGLE_QUOTES) != 0) {
25992623 return _handleApos();
26002624 }
26012625 break;
26022626 case 'N':
26032627 _matchToken("NaN", 1);
2604 if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) {
2628 if ((_features & FEAT_MASK_NON_NUM_NUMBERS) != 0) {
26052629 return resetAsNaN("NaN", Double.NaN);
26062630 }
26072631 _reportError("Non-standard token 'NaN': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow");
26082632 break;
26092633 case 'I':
26102634 _matchToken("Infinity", 1);
2611 if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) {
2635 if ((_features & FEAT_MASK_NON_NUM_NUMBERS) != 0) {
26122636 return resetAsNaN("Infinity", Double.POSITIVE_INFINITY);
26132637 }
26142638 _reportError("Non-standard token 'Infinity': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow");
26232647 }
26242648 // [core#77] Try to decode most likely token
26252649 if (Character.isJavaIdentifierStart(c)) {
2626 _reportInvalidToken(""+((char) c), "('true', 'false' or 'null')");
2650 _reportInvalidToken(""+((char) c), _validJsonTokenList());
26272651 }
26282652 // but if it doesn't look like a token:
2629 _reportUnexpectedChar(c, "expected a valid value (number, String, array, object, 'true', 'false' or 'null')");
2653 _reportUnexpectedChar(c, "expected a valid value "+_validJsonValueList());
26302654 return null;
26312655 }
26322656
27472771 break;
27482772 }
27492773 _matchToken(match, 3);
2750 if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) {
2774 if ((_features & FEAT_MASK_NON_NUM_NUMBERS) != 0) {
27512775 return resetAsNaN(match, neg ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY);
27522776 }
27532777 _reportError("Non-standard token '%s': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow",
30993123
31003124 private final void _skipComment() throws IOException
31013125 {
3102 if (!isEnabled(Feature.ALLOW_COMMENTS)) {
3126 if ((_features & FEAT_MASK_ALLOW_JAVA_COMMENTS) == 0) {
31033127 _reportUnexpectedChar('/', "maybe a (non-standard) comment? (not recognized as one since Feature 'ALLOW_COMMENTS' not enabled for parser)");
31043128 }
31053129 // First: check which comment (if either) it is:
31643188
31653189 private final boolean _skipYAMLComment() throws IOException
31663190 {
3167 if (!isEnabled(Feature.ALLOW_YAML_COMMENTS)) {
3191 if ((_features & FEAT_MASK_ALLOW_YAML_COMMENTS) == 0) {
31683192 return false;
31693193 }
31703194 _skipLine();
32563280 _reportInvalidEOF(" in character escape sequence", JsonToken.VALUE_STRING);
32573281 }
32583282 }
3259 int ch = (int) _inputBuffer[_inputPtr++];
3283 int ch = _inputBuffer[_inputPtr++] & 0xFF;
32603284 int digit = CharTypes.charToHex(ch);
32613285 if (digit < 0) {
32623286 _reportUnexpectedChar(ch, "expected a hex-digit for character escape sequence");
35003524
35013525 protected void _reportInvalidToken(String matchedPart, int ptr) throws IOException {
35023526 _inputPtr = ptr;
3503 _reportInvalidToken(matchedPart, "'null', 'true', 'false' or NaN");
3527 _reportInvalidToken(matchedPart, _validJsonTokenList());
35043528 }
35053529
35063530 protected void _reportInvalidToken(String matchedPart) throws IOException {
3507 _reportInvalidToken(matchedPart, "'null', 'true', 'false' or NaN");
3531 _reportInvalidToken(matchedPart, _validJsonTokenList());
35083532 }
35093533
35103534 protected void _reportInvalidToken(String matchedPart, String msg) throws IOException
3131 /**
3232 * Character used for quoting JSON Object property names
3333 * and String values.
34 *
35 * @since 2.8
36 */
37 protected char _quoteChar = '"'; // TODO: make configurable
34 */
35 protected char _quoteChar;
3836
3937 /*
4038 /**********************************************************
8179 * Intermediate buffer in which characters of a String are copied
8280 * before being encoded.
8381 *
84 * @since 2.9
85 */
86 protected char[] _charBuffer;
82 * @since 2.10
83 */
84 protected char[] _copyBuffer;
8785
8886 /*
8987 /**********************************************************
9189 /**********************************************************
9290 */
9391
92 @Deprecated // since 2.10
9493 public WriterBasedJsonGenerator(IOContext ctxt, int features,
95 ObjectCodec codec, Writer w)
94 ObjectCodec codec, Writer w) {
95 this(ctxt, features, codec, w, JsonFactory.DEFAULT_QUOTE_CHAR);
96 }
97
98 /**
99 * @since 2.10
100 */
101 public WriterBasedJsonGenerator(IOContext ctxt, int features,
102 ObjectCodec codec, Writer w,
103 char quoteChar)
104
96105 {
97106 super(ctxt, features, codec);
98107 _writer = w;
99108 _outputBuffer = ctxt.allocConcatBuffer();
100109 _outputEnd = _outputBuffer.length;
110 _quoteChar = quoteChar;
111 if (quoteChar != '"') { // since 2.10
112 _outputEscapes = CharTypes.get7BitOutputEscapes(quoteChar);
113 }
101114 }
102115
103116 /*
192205 _outputBuffer[_outputTail++] = ',';
193206 }
194207 // Alternate mode, in which quoting of field names disabled?
208 if (_cfgUnqNames) {
209 final char[] ch = name.asQuotedChars();
210 writeRaw(ch, 0, ch.length);
211 return;
212 }
213 // we know there's room for at least one more char
214 _outputBuffer[_outputTail++] = _quoteChar;
215 // The beef:
216
217 int len = name.appendQuoted(_outputBuffer, _outputTail);
218 if (len < 0) {
219 _writeFieldNameTail(name);
220 return;
221 }
222 _outputTail += len;
223 if (_outputTail >= _outputEnd) {
224 _flushBuffer();
225 }
226 _outputBuffer[_outputTail++] = _quoteChar;
227 }
228
229 private final void _writeFieldNameTail(SerializableString name) throws IOException
230 {
195231 final char[] quoted = name.asQuotedChars();
196 if (_cfgUnqNames) {
197 writeRaw(quoted, 0, quoted.length);
198 return;
199 }
200 // we know there's room for at least one more char
201 _outputBuffer[_outputTail++] = _quoteChar;
202 // The beef:
203 final int qlen = quoted.length;
204 if ((_outputTail + qlen + 1) >= _outputEnd) {
205 writeRaw(quoted, 0, qlen);
206 // and closing quotes; need room for one more char:
207 if (_outputTail >= _outputEnd) {
208 _flushBuffer();
209 }
210 _outputBuffer[_outputTail++] = _quoteChar;
211 } else {
212 System.arraycopy(quoted, 0, _outputBuffer, _outputTail, qlen);
213 _outputTail += qlen;
214 _outputBuffer[_outputTail++] = _quoteChar;
215 }
216 }
217
232 writeRaw(quoted, 0, quoted.length);
233 if (_outputTail >= _outputEnd) {
234 _flushBuffer();
235 }
236 _outputBuffer[_outputTail++] = _quoteChar;
237 }
238
218239 /*
219240 /**********************************************************
220241 /* Output method implementations, structural
236257 }
237258 }
238259
260 @Override // since 2.10
261 public void writeStartArray(int size) throws IOException
262 {
263 _verifyValueWrite("start an array");
264 _writeContext = _writeContext.createChildArrayContext();
265 if (_cfgPrettyPrinter != null) {
266 _cfgPrettyPrinter.writeStartArray(this);
267 } else {
268 if (_outputTail >= _outputEnd) {
269 _flushBuffer();
270 }
271 _outputBuffer[_outputTail++] = '[';
272 }
273 }
274
239275 @Override
240276 public void writeEndArray() throws IOException
241277 {
253289 _writeContext = _writeContext.clearAndGetParent();
254290 }
255291
256 @Override // since 2.8
257 public void writeStartObject(Object forValue) throws IOException
258 {
259 _verifyValueWrite("start an object");
260 JsonWriteContext ctxt = _writeContext.createChildObjectContext();
261 _writeContext = ctxt;
262 if (forValue != null) {
263 ctxt.setCurrentValue(forValue);
264 }
265 if (_cfgPrettyPrinter != null) {
266 _cfgPrettyPrinter.writeStartObject(this);
267 } else {
268 if (_outputTail >= _outputEnd) {
269 _flushBuffer();
270 }
271 _outputBuffer[_outputTail++] = '{';
272 }
273 }
274
275292 @Override
276293 public void writeStartObject() throws IOException
277294 {
287304 }
288305 }
289306
307 @Override // since 2.8
308 public void writeStartObject(Object forValue) throws IOException
309 {
310 _verifyValueWrite("start an object");
311 JsonWriteContext ctxt = _writeContext.createChildObjectContext(forValue);
312 _writeContext = ctxt;
313 if (_cfgPrettyPrinter != null) {
314 _cfgPrettyPrinter.writeStartObject(this);
315 } else {
316 if (_outputTail >= _outputEnd) {
317 _flushBuffer();
318 }
319 _outputBuffer[_outputTail++] = '{';
320 }
321 }
322
290323 @Override
291324 public void writeEndObject() throws IOException
292325 {
338371 } else {
339372 _cfgPrettyPrinter.beforeObjectEntries(this);
340373 }
341
342374 final char[] quoted = name.asQuotedChars();
343375 if (_cfgUnqNames) {// non-standard, omit quotes
344376 writeRaw(quoted, 0, quoted.length);
388420 _reportError("null reader");
389421 }
390422 int toRead = (len >= 0) ? len : Integer.MAX_VALUE;
391 final char[] buf = _allocateCopyBuffer();
392423 //Add leading quote
393424 if ((_outputTail + len) >= _outputEnd) {
394425 _flushBuffer();
395426 }
396427 _outputBuffer[_outputTail++] = _quoteChar;
397428
429 final char[] buf = _allocateCopyBuffer();
398430 //read
399431 while (toRead > 0) {
400432 int toReadNow = Math.min(toRead, buf.length);
445477 _flushBuffer();
446478 }
447479 _outputBuffer[_outputTail++] = _quoteChar;
480 int len = sstr.appendQuoted(_outputBuffer, _outputTail);
481 if (len < 0) {
482 _writeString2(sstr);
483 return;
484 }
485 _outputTail += len;
486 if (_outputTail >= _outputEnd) {
487 _flushBuffer();
488 }
489 _outputBuffer[_outputTail++] = _quoteChar;
490 }
491
492 private void _writeString2(SerializableString sstr) throws IOException
493 {
448494 // Note: copied from writeRaw:
449495 char[] text = sstr.asQuotedChars();
450496 final int len = text.length;
451 // Only worth buffering if it's a short write?
452497 if (len < SHORT_WRITE) {
453498 int room = _outputEnd - _outputTail;
454499 if (len > room) {
457502 System.arraycopy(text, 0, _outputBuffer, _outputTail, len);
458503 _outputTail += len;
459504 } else {
460 // Otherwise, better just pass through:
461505 _flushBuffer();
462506 _writer.write(text, 0, len);
463507 }
466510 }
467511 _outputBuffer[_outputTail++] = _quoteChar;
468512 }
469
513
470514 @Override
471515 public void writeRawUTF8String(byte[] text, int offset, int length) throws IOException {
472516 // could add support for buffering if we really want it...
527571 // @since 2.1
528572 @Override
529573 public void writeRaw(SerializableString text) throws IOException {
530 writeRaw(text.getValue());
574 int len = text.appendUnquoted(_outputBuffer, _outputTail);
575 if (len < 0) {
576 writeRaw(text.getValue());
577 return;
578 }
579 _outputTail += len;
531580 }
532581
533582 @Override
733782 }
734783 }
735784
736
785 @SuppressWarnings("deprecation")
737786 @Override
738787 public void writeNumber(double d) throws IOException
739788 {
740789 if (_cfgNumbersAsStrings ||
741 // [JACKSON-139]
742 (isEnabled(Feature.QUOTE_NON_NUMERIC_NUMBERS) && ((Double.isNaN(d) || Double.isInfinite(d))))) {
790 (NumberOutput.notFinite(d) && isEnabled(Feature.QUOTE_NON_NUMERIC_NUMBERS))) {
743791 writeString(String.valueOf(d));
744792 return;
745793 }
748796 writeRaw(String.valueOf(d));
749797 }
750798
799 @SuppressWarnings("deprecation")
751800 @Override
752801 public void writeNumber(float f) throws IOException
753802 {
754803 if (_cfgNumbersAsStrings ||
755 // [JACKSON-139]
756 (isEnabled(Feature.QUOTE_NON_NUMERIC_NUMBERS) && ((Float.isNaN(f) || Float.isInfinite(f))))) {
804 (NumberOutput.notFinite(f) && isEnabled(Feature.QUOTE_NON_NUMERIC_NUMBERS))) {
757805 writeString(String.valueOf(f));
758806 return;
759807 }
940988 _outputBuffer = null;
941989 _ioContext.releaseConcatBuffer(buf);
942990 }
943 buf = _charBuffer;
991 buf = _copyBuffer;
944992 if (buf != null) {
945 _charBuffer = null;
993 _copyBuffer = null;
946994 _ioContext.releaseNameCopyBuffer(buf);
947995 }
948996 }
19301978 * @since 2.9
19311979 */
19321980 private char[] _allocateCopyBuffer() {
1933 if (_charBuffer == null) {
1934 _charBuffer = _ioContext.allocNameCopyBuffer(2000);
1935 }
1936 return _charBuffer;
1981 if (_copyBuffer == null) {
1982 _copyBuffer = _ioContext.allocNameCopyBuffer(2000);
1983 }
1984 return _copyBuffer;
19371985 }
19381986
19391987 protected void _flushBuffer() throws IOException
1414 extends NonBlockingJsonParserBase
1515 implements ByteArrayFeeder
1616 {
17 @SuppressWarnings("deprecation")
18 private final static int FEAT_MASK_TRAILING_COMMA = Feature.ALLOW_TRAILING_COMMA.getMask();
19 @SuppressWarnings("deprecation")
20 private final static int FEAT_MASK_LEADING_ZEROS = Feature.ALLOW_NUMERIC_LEADING_ZEROS.getMask();
21 @SuppressWarnings("deprecation")
22 private final static int FEAT_MASK_ALLOW_MISSING = Feature.ALLOW_MISSING_VALUES.getMask();
23 private final static int FEAT_MASK_ALLOW_SINGLE_QUOTES = Feature.ALLOW_SINGLE_QUOTES.getMask();
24 private final static int FEAT_MASK_ALLOW_UNQUOTED_NAMES = Feature.ALLOW_UNQUOTED_FIELD_NAMES.getMask();
25 private final static int FEAT_MASK_ALLOW_JAVA_COMMENTS = Feature.ALLOW_COMMENTS.getMask();
26 private final static int FEAT_MASK_ALLOW_YAML_COMMENTS = Feature.ALLOW_YAML_COMMENTS.getMask();
27
1728 // This is the main input-code lookup table, fetched eagerly
1829 private final static int[] _icUTF8 = CharTypes.getInputCodeUtf8();
1930
552563 _updateTokenLocation();
553564 if (ch != INT_QUOTE) {
554565 if (ch == INT_RCURLY) {
555 if (JsonParser.Feature.ALLOW_TRAILING_COMMA.enabledIn(_features)) {
566 if ((_features & FEAT_MASK_TRAILING_COMMA) != 0) {
556567 return _closeObjectScope();
557568 }
558569 }
590601 }
591602 }
592603 _updateTokenLocation();
604 // 17-Sep-2019, tatu: [core#563] Need to call this to update index within array
605 _parsingContext.expectComma();
606
593607 if (ch == INT_QUOTE) {
594608 return _startString();
595609 }
624638 return _startTrueToken();
625639 case '[':
626640 return _startArrayScope();
627 case ']':
641 case INT_RBRACKET:
628642 return _closeArrayScope();
629643 case '{':
630644 return _startObjectScope();
631 case '}':
645 case INT_RCURLY:
632646 return _closeObjectScope();
633647 default:
634648 }
664678 }
665679 _reportUnexpectedChar(ch, "was expecting comma to separate "+_parsingContext.typeDesc()+" entries");
666680 }
681
682 // 17-Sep-2019, tatu: [core#563] Need to call this to update index within array
683 _parsingContext.expectComma();
684
667685 int ptr = _inputPtr;
668686 if (ptr >= _inputEnd) {
669687 _minorState = MINOR_VALUE_WS_AFTER_COMMA;
710728 return _startTrueToken();
711729 case '[':
712730 return _startArrayScope();
713 case ']':
731 case INT_RBRACKET:
714732 // Was that a trailing comma?
715 if (isEnabled(Feature.ALLOW_TRAILING_COMMA)) {
733 if ((_features & FEAT_MASK_TRAILING_COMMA) != 0) {
716734 return _closeArrayScope();
717735 }
718736 break;
719737 case '{':
720738 return _startObjectScope();
721 case '}':
739 case INT_RCURLY:
722740 // Was that a trailing comma?
723 if (isEnabled(Feature.ALLOW_TRAILING_COMMA)) {
741 if ((_features & FEAT_MASK_TRAILING_COMMA) != 0) {
724742 return _closeObjectScope();
725743 }
726744 break;
854872 return _startTrueToken();
855873 case '[':
856874 return _startArrayScope();
857 case ']':
875 case INT_RBRACKET:
858876 // Was that a trailing comma?
859 if (isEnabled(Feature.ALLOW_TRAILING_COMMA)) {
877 if ((_features & FEAT_MASK_TRAILING_COMMA) != 0) {
860878 return _closeArrayScope();
861879 }
862880 break;
863881 case '{':
864882 return _startObjectScope();
865 case '}':
883 case INT_RCURLY:
866884 // Was that a trailing comma?
867 if (isEnabled(Feature.ALLOW_TRAILING_COMMA)) {
885 if ((_features & FEAT_MASK_TRAILING_COMMA) != 0) {
868886 return _closeObjectScope();
869887 }
870888 break;
876894 protected JsonToken _startUnexpectedValue(boolean leadingComma, int ch) throws IOException
877895 {
878896 switch (ch) {
879 case ']':
897 case INT_RBRACKET:
880898 if (!_parsingContext.inArray()) {
881899 break;
882900 }
885903 // 28-Mar-2016: [core#116]: If Feature.ALLOW_MISSING_VALUES is enabled
886904 // we may allow "missing values", that is, encountering a trailing
887905 // comma or closing marker where value would be expected
888 if (isEnabled(Feature.ALLOW_MISSING_VALUES)) {
906 if ((_features & FEAT_MASK_ALLOW_MISSING) != 0) {
889907 --_inputPtr;
890908 return _valueComplete(JsonToken.VALUE_NULL);
891909 }
892910 // fall through
893 case '}':
911 case INT_RCURLY:
894912 // Error: neither is valid at this point; valid closers have
895913 // been handled earlier
896914 break;
897915 case '\'':
898 if (isEnabled(Feature.ALLOW_SINGLE_QUOTES)) {
916 if ((_features & FEAT_MASK_ALLOW_SINGLE_QUOTES) != 0) {
899917 return _startAposString();
900918 }
901919 break;
907925 return _finishNonStdToken(NON_STD_TOKEN_INFINITY, 1);
908926 }
909927 // !!! TODO: maybe try to collect more information for better diagnostics
910 _reportUnexpectedChar(ch, "expected a valid value (number, String, array, object, 'true', 'false' or 'null')");
928 _reportUnexpectedChar(ch, "expected a valid value "+_validJsonValueList());
911929 return null;
912930 }
913931
942960
943961 private final JsonToken _startSlashComment(int fromMinorState) throws IOException
944962 {
945 if (!JsonParser.Feature.ALLOW_COMMENTS.enabledIn(_features)) {
963 if ((_features & FEAT_MASK_ALLOW_JAVA_COMMENTS) == 0) {
946964 _reportUnexpectedChar('/', "maybe a (non-standard) comment? (not recognized as one since Feature 'ALLOW_COMMENTS' not enabled for parser)");
947965 }
948966
966984 private final JsonToken _finishHashComment(int fromMinorState) throws IOException
967985 {
968986 // Could by-pass this check by refactoring, but for now simplest way...
969 if (!JsonParser.Feature.ALLOW_YAML_COMMENTS.enabledIn(_features)) {
987 if ((_features & FEAT_MASK_ALLOW_YAML_COMMENTS) == 0) {
970988 _reportUnexpectedChar('#', "maybe a (non-standard) comment? (not recognized as one since Feature 'ALLOW_YAML_COMMENTS' not enabled for parser)");
971989 }
972990 while (true) {
12511269 {
12521270 // !!! TODO: Include non-standard ones if enabled
12531271 _reportError("Unrecognized token '%s': was expecting %s", _textBuffer.contentsAsString(),
1254 "'null', 'true' or 'false'");
1272 _validJsonTokenList());
12551273 return JsonToken.NOT_AVAILABLE; // never gets here
12561274 }
1257
1275
12581276 /*
12591277 /**********************************************************************
12601278 /* Second-level decoding, Number decoding
14761494 } else { // Number between 0 and 9
14771495 // although not guaranteed, seems likely valid separator (white space,
14781496 // comma, end bracket/curly); next time token needed will verify
1479 if (!isEnabled(Feature.ALLOW_NUMERIC_LEADING_ZEROS)) {
1497 if ((_features & FEAT_MASK_LEADING_ZEROS) == 0) {
14801498 reportInvalidNumber("Leading zeroes not allowed");
14811499 }
14821500 if (ch == INT_0) { // coalesce multiple leading zeroes into just one
15291547 } else { // Number between 1 and 9; go integral
15301548 // although not guaranteed, seems likely valid separator (white space,
15311549 // comma, end bracket/curly); next time token needed will verify
1532 if (!isEnabled(Feature.ALLOW_NUMERIC_LEADING_ZEROS)) {
1550 if ((_features & FEAT_MASK_LEADING_ZEROS) == 0) {
15331551 reportInvalidNumber("Leading zeroes not allowed");
15341552 }
15351553 if (ch == INT_0) { // coalesce multiple leading zeroes into just one
20482066 case '#':
20492067 // Careful, since this may alternatively be leading char of
20502068 // unquoted name...
2051 if (JsonParser.Feature.ALLOW_YAML_COMMENTS.enabledIn(_features)) {
2069 if ((_features & FEAT_MASK_ALLOW_YAML_COMMENTS) != 0) {
20522070 return _finishHashComment(MINOR_FIELD_LEADING_WS);
20532071 }
20542072 break;
20552073 case '/':
20562074 return _startSlashComment(MINOR_FIELD_LEADING_WS);
20572075 case '\'':
2058 if (isEnabled(Feature.ALLOW_SINGLE_QUOTES)) {
2076 if ((_features & FEAT_MASK_ALLOW_SINGLE_QUOTES) != 0) {
20592077 return _finishAposName(0, 0, 0);
20602078 }
20612079 break;
2062 case ']': // for better error reporting...
2080 case INT_RBRACKET: // for better error reporting...
20632081 return _closeArrayScope();
20642082 }
20652083 // allow unquoted names if feature enabled:
2066 if (!isEnabled(Feature.ALLOW_UNQUOTED_FIELD_NAMES)) {
2084 if ((_features & FEAT_MASK_ALLOW_UNQUOTED_NAMES) == 0) {
20672085 // !!! TODO: Decode UTF-8 characters properly...
20682086 // char c = (char) _decodeCharForError(ch);
20692087 char c = (char) ch;
835835 return t;
836836 }
837837
838 @SuppressWarnings("deprecation")
838839 protected final JsonToken _valueNonStdNumberComplete(int type) throws IOException
839840 {
840841 String tokenStr = NON_STD_TOKENS[type];
1010 * memory access due to flattening of name quad data.
1111 * Performance improvement modest for simple JSON document data binding (maybe 3%),
1212 * but should help more for larger symbol tables, or for binary formats like Smile.
13 *<p>
14 * Hash area is divided into 4 sections:
15 *<ol>
16 * <li>Primary area (1/2 of total size), direct match from hash (LSB)</li>
17 * <li>Secondary area (1/4 of total size), match from {@code hash (LSB) >> 1}</li>
18 * <li>Tertiary area (1/8 of total size), match from {@code hash (LSB) >> 2}</li>
19 * <li>Spill-over area (remaining 1/8) with linear scan, insertion order</li>
20 * <li></li>
21 * </ol>
22 * and within every area, entries are 4 {@code int}s, where 1 - 3 ints contain 1 - 12
23 * UTF-8 encoded bytes of name (null-padded), and last int is offset in
24 * {@code _names} that contains actual name Strings.
1325 *
1426 * @since 2.6
1527 */
1729 {
1830 /**
1931 * Initial size of the primary hash area. Each entry consumes 4 ints (16 bytes),
20 * and secondary area is same as primary; so default size will use 2kB of memory_tertiaryStart
32 * and secondary area is same as primary; so default size will use 2kB of memory
2133 * (plus 64x4 or 64x8 (256/512 bytes) for references to Strings, and Strings
2234 * themselves).
2335 */
2638
2739 /**
2840 * Let's not expand symbol tables past some maximum size;
29 * this should protected against OOMEs caused by large documents
3041 * with unique (~= random) names.
3142 * Size is in
3243 */
168179
169180 /**
170181 * Offset within {@link #_hashArea} that follows main slots and contains
171 * quads for longer names (13 bytes or longers), and points to the
182 * quads for longer names (13 bytes or longer), and points to the
172183 * first available int that may be used for appending quads of the next
173184 * long name.
174185 * Note that long name area follows immediately after the fixed-size
175186 * main hash area ({@link #_hashArea}).
176187 */
177188 private int _longNameOffset;
178
179 /**
180 * This flag is set if, after adding a new entry, it is deemed
181 * that a rehash is warranted if any more entries are to be added.
182 */
183 private transient boolean _needRehash;
184189
185190 /*
186191 /**********************************************************
266271 _longNameOffset = state.longNameOffset;
267272
268273 // and then set other state to reflect sharing status
269 _needRehash = false;
270274 _hashShared = true;
271275 }
272276
316320 public void release()
317321 {
318322 // we will try to merge if child table has new entries
319 if (_parent != null && maybeDirty()) {
323 // 28-Jul-2019, tatu: From [core#548]: do not share if immediate rehash needed
324 if ((_parent != null) && maybeDirty()) {
320325 _parent.mergeChild(new TableInfo(this));
321326 // Let's also mark this instance as dirty, so that just in
322327 // case release was too early, there's no corruption of possibly shared data.
767772 _hashArea[offset+3] = 1;
768773 _names[offset >> 2] = name;
769774 ++_count;
770 _verifyNeedForRehash();
771775 return name;
772776 }
773777
783787 _hashArea[offset+3] = 2;
784788 _names[offset >> 2] = name;
785789 ++_count;
786 _verifyNeedForRehash();
787790 return name;
788791 }
789792
799802 _hashArea[offset+3] = 3;
800803 _names[offset >> 2] = name;
801804 ++_count;
802 _verifyNeedForRehash();
803805 return name;
804806 }
805807
850852
851853 // and finally; see if we really should rehash.
852854 ++_count;
853 _verifyNeedForRehash();
854855 return name;
855 }
856
857 private void _verifyNeedForRehash() {
858 // Yes if above 80%, or above 50% AND have ~1% spill-overs
859 if (_count > (_hashSize >> 1)) { // over 50%
860 int spillCount = (_spilloverEnd - _spilloverStart()) >> 2;
861 if ((spillCount > (1 + _count >> 7))
862 || (_count > (_hashSize * 0.80))) {
863 _needRehash = true;
864 }
865 }
866856 }
867857
868858 private void _verifySharing()
871861 _hashArea = Arrays.copyOf(_hashArea, _hashArea.length);
872862 _names = Arrays.copyOf(_names, _names.length);
873863 _hashShared = false;
874 // 09-Sep-2015, tatu: As per [jackson-core#216], also need to ensure
875 // we rehash as needed, as need-rehash flag is not copied from parent
876 _verifyNeedForRehash();
877 }
878 if (_needRehash) {
879 rehash();
880864 }
881865 }
882866
885869 */
886870 private int _findOffsetForAdd(int hash)
887871 {
888 // first, check the primary:
872 // first, check the primary: if slot found, no need for resize
889873 int offset = _calcOffset(hash);
890874 final int[] hashArea = _hashArea;
891875 if (hashArea[offset+3] == 0) {
892876 //System.err.printf(" PRImary slot #%d, hash %X\n", (offset>>2), hash & 0x7F);
893877 return offset;
894878 }
895 // then secondary
879
880 // Otherwise let's see if we are due resize():
881 if (_checkNeedForRehash()) {
882 return _resizeAndFindOffsetForAdd(hash);
883 }
884
885 // If not, proceed with secondary slot
896886 int offset2 = _secondaryStart + ((offset >> 3) << 2);
897887 if (hashArea[offset2+3] == 0) {
898888 //System.err.printf(" SECondary slot #%d (start x%X), hash %X\n",(offset >> 3), _secondaryStart, (hash & 0x7F));
926916 if (_failOnDoS) {
927917 _reportTooManyCollisions();
928918 }
929 // and if we didn't fail, we'll simply force rehash for next add
930 // (which, in turn, may double up or nuke contents, depending on size etc)
931 _needRehash = true;
919 return _resizeAndFindOffsetForAdd(hash);
932920 }
933921 return offset;
934922 }
935923
924 // @since 2.10
925 private int _resizeAndFindOffsetForAdd(int hash)
926 {
927 // First things first: we need to resize+rehash (or, if too big, nuke contents)
928 rehash();
929
930 // Copy of main _findOffsetForAdd except for checks to resize: can not be needed
931 int offset = _calcOffset(hash);
932 final int[] hashArea = _hashArea;
933 if (hashArea[offset+3] == 0) {
934 return offset;
935 }
936 int offset2 = _secondaryStart + ((offset >> 3) << 2);
937 if (hashArea[offset2+3] == 0) {
938 return offset2;
939 }
940 offset2 = _tertiaryStart + ((offset >> (_tertiaryShift + 2)) << _tertiaryShift);
941 final int bucketSize = (1 << _tertiaryShift);
942 for (int end = offset2 + bucketSize; offset2 < end; offset2 += 4) {
943 if (hashArea[offset2+3] == 0) {
944 return offset2;
945 }
946 }
947 offset = _spilloverEnd;
948 _spilloverEnd += 4;
949 return offset;
950 }
951
952 // Helper method for checking if we should simply rehash() before add
953 private boolean _checkNeedForRehash() {
954 // Yes if above 80%, or above 50% AND have ~1% spill-overs
955 if (_count > (_hashSize >> 1)) { // over 50%
956 int spillCount = (_spilloverEnd - _spilloverStart()) >> 2;
957 if ((spillCount > (1 + _count >> 7))
958 || (_count > (_hashSize * 0.80))) {
959 return true;
960 }
961 }
962 return false;
963 }
964
936965 private int _appendLongName(int[] quads, int qlen)
937966 {
938967 int start = _longNameOffset;
10601089
10611090 private void rehash()
10621091 {
1063 _needRehash = false;
10641092 // Note: since we'll make copies, no need to unshare, can just mark as such:
10651093 _hashShared = false;
10661094
7777 /**
7878 * Also: to thwart attacks based on hash collisions (which may or may not
7979 * be cheap to calculate), we will need to detect "too long"
80 * collision chains. Let's start with static value of 255 entries
80 * collision chains. Let's start with static value of 100 entries
8181 * for the longest legal chain.
8282 *<p>
8383 * Note: longest chain we have been able to produce without malicious
8484 * intent has been 38 (with "com.fasterxml.jackson.core.main.TestWithTonsaSymbols");
8585 * our setting should be reasonable here.
86 *<p>
87 * Also note that value was lowered from 255 (2.3 and earlier) to 100 for 2.4
8886 *
8987 * @since 2.1
9088 */
480478 _hashShared = false;
481479 } else if (_size >= _sizeThreshold) { // Need to expand?
482480 rehash();
483 /* Need to recalc hash; rare occurence (index mask has been
484 * recalculated as part of rehash)
485 */
481 // Need to recalc hash; rare occurrence (index mask has been
482 // recalculated as part of rehash)
486483 index = _hashToIndex(calcHash(buffer, start, len));
487484 }
488485
501498 if (collLen > MAX_COLL_CHAIN_LENGTH) {
502499 // 23-May-2014, tatu: Instead of throwing an exception right away,
503500 // let's handle in bit smarter way.
504 _handleSpillOverflow(bix, newB);
501 _handleSpillOverflow(bix, newB, index);
505502 } else {
506503 _buckets[bix] = newB;
507504 _longestCollisionList = Math.max(collLen, _longestCollisionList);
510507 return newSymbol;
511508 }
512509
513 private void _handleSpillOverflow(int bindex, Bucket newBucket)
510 /**
511 * Method called when an overflow bucket has hit the maximum expected length:
512 * this may be a case of DoS attack. Deal with it based on settings by either
513 * clearing up bucket (to avoid indefinite expansion) or throwing exception.
514 * Currently the first overflow for any single bucket DOES NOT throw an exception,
515 * only second time (per symbol table instance)
516 */
517 private void _handleSpillOverflow(int bucketIndex, Bucket newBucket, int mainIndex)
514518 {
515519 if (_overflows == null) {
516520 _overflows = new BitSet();
517 _overflows.set(bindex);
521 _overflows.set(bucketIndex);
518522 } else {
519 if (_overflows.get(bindex)) {
520 // Has happened once already, so not a coincident...
523 if (_overflows.get(bucketIndex)) {
524 // Has happened once already for this bucket index, so probably not coincidental...
521525 if (JsonFactory.Feature.FAIL_ON_SYMBOL_HASH_OVERFLOW.enabledIn(_flags)) {
522526 reportTooManyCollisions(MAX_COLL_CHAIN_LENGTH);
523527 }
524 // but even if we don't fail, we will stop canonicalizing:
528 // but even if we don't fail, we will stop canonicalizing as safety measure
529 // (so as not to cause problems with PermGen)
525530 _canonicalize = false;
526531 } else {
527 _overflows.set(bindex);
528 }
529 }
532 _overflows.set(bucketIndex);
533 }
534 }
535
530536 // regardless, if we get this far, clear up the bucket, adjust size appropriately.
531 _symbols[bindex + bindex] = newBucket.symbol;
532 _buckets[bindex] = null;
533 // newBucket contains new symbol; but we wil
537 _symbols[mainIndex] = newBucket.symbol;
538 _buckets[bucketIndex] = null;
539 // newBucket contains new symbol; but we will
534540 _size -= (newBucket.length);
535541 // we could calculate longest; but for now just mark as invalid
536542 _longestCollisionList = -1;
603609 * entries.
604610 */
605611 private void rehash() {
606 int size = _symbols.length;
612 final int size = _symbols.length;
607613 int newSize = size + size;
608614
609615 /* 12-Mar-2010, tatu: Let's actually limit maximum size we are
623629 return;
624630 }
625631
626 String[] oldSyms = _symbols;
627 Bucket[] oldBuckets = _buckets;
632 final String[] oldSyms = _symbols;
633 final Bucket[] oldBuckets = _buckets;
628634 _symbols = new String[newSize];
629635 _buckets = new Bucket[newSize >> 1];
630636 // Let's update index mask, threshold, now (needed for rehashing)
652658 }
653659 }
654660
655 size >>= 1;
656 for (int i = 0; i < size; ++i) {
661 final int bucketSize = (size >> 1);
662 for (int i = 0; i < bucketSize; ++i) {
657663 Bucket b = oldBuckets[i];
658664 while (b != null) {
659665 ++count;
688694 +") now exceeds maximum, "+maxLen+" -- suspect a DoS attack based on hash collisions");
689695 }
690696
697 // since 2.10, for tests only
698 /**
699 * Diagnostics method that will verify that internal data structures are consistent;
700 * not meant as user-facing method but only for test suites and possible troubleshooting.
701 *
702 * @since 2.10
703 */
704 protected void verifyInternalConsistency() {
705 int count = 0;
706 final int size = _symbols.length;
707
708 for (int i = 0; i < size; ++i) {
709 String symbol = _symbols[i];
710 if (symbol != null) {
711 ++count;
712 }
713 }
714
715 final int bucketSize = (size >> 1);
716 for (int i = 0; i < bucketSize; ++i) {
717 for (Bucket b = _buckets[i]; b != null; b = b.next) {
718 ++count;
719 }
720 }
721 if (count != _size) {
722 throw new IllegalStateException(String.format("Internal error: expected internal size %d vs calculated count %d",
723 _size, count));
724 }
725 }
726
691727 // For debugging, comment out
692728 /*
693729 @Override
00 package com.fasterxml.jackson.core.util;
1
2 import java.util.concurrent.atomic.AtomicReferenceArray;
13
24 /**
35 * This is a small utility class, whose main functionality is to allow
68 * instance of this class through a <code>SoftReference</code>. The
79 * end result is a low-overhead GC-cleanable recycling: hopefully
810 * ideal for use by stream readers.
11 *<p>
12 * Rewritten in 2.10 to be thread-safe (see [jackson-core#479] for details),
13 * to not rely on {@code ThreadLocal} access.
914 */
1015 public class BufferRecycler
1116 {
3439 */
3540 public final static int BYTE_BASE64_CODEC_BUFFER = 3;
3641
37 public final static int CHAR_TOKEN_BUFFER = 0; // Tokenizable input
38 public final static int CHAR_CONCAT_BUFFER = 1; // concatenated output
39 public final static int CHAR_TEXT_BUFFER = 2; // Text content from input
40 public final static int CHAR_NAME_COPY_BUFFER = 3; // Temporary buffer for getting name characters
42 /**
43 * Buffer used as input buffer for tokenization for character-based parsers.
44 */
45 public final static int CHAR_TOKEN_BUFFER = 0;
4146
42 // Buffer lengths, defined in 2.4 (smaller before that)
47 /**
48 * Buffer used by generators; for byte-backed generators for buffering of
49 * {@link String} values to output (before encoding into UTF-8),
50 * and for char-backed generators as actual concatenation buffer.
51 */
52 public final static int CHAR_CONCAT_BUFFER = 1;
53
54 /**
55 * Used through {@link TextBuffer}: directly by parsers (to concatenate
56 * String values)
57 * and indirectly via
58 * {@link com.fasterxml.jackson.core.io.SegmentedStringWriter}
59 * when serializing (databind level {@code ObjectMapper} and
60 * {@code ObjectWriter}). In both cases used as segments (and not for whole value),
61 * but may result in retention of larger chunks for big content
62 * (long text values during parsing; bigger output documents for generation).
63 */
64 public final static int CHAR_TEXT_BUFFER = 2;
65
66 /**
67 * For parsers, temporary buffer into which {@code char[]} for names is copied
68 * when requested as such; for {@code WriterBasedGenerator} used for buffering
69 * during {@code writeString(Reader)} operation (not commonly used).
70 */
71 public final static int CHAR_NAME_COPY_BUFFER = 3;
72
73 // Buffer lengths
4374
4475 private final static int[] BYTE_BUFFER_LENGTHS = new int[] { 8000, 8000, 2000, 2000 };
4576 private final static int[] CHAR_BUFFER_LENGTHS = new int[] { 4000, 4000, 200, 200 };
46
47 final protected byte[][] _byteBuffers;
48 final protected char[][] _charBuffers;
77
78 // Note: changed from simple array in 2.10:
79 protected final AtomicReferenceArray<byte[]> _byteBuffers;
80
81 // Note: changed from simple array in 2.10:
82 protected final AtomicReferenceArray<char[]> _charBuffers;
4983
5084 /*
5185 /**********************************************************
5286 /* Construction
5387 /**********************************************************
5488 */
55
89
5690 /**
5791 * Default constructor used for creating instances of this default
5892 * implementation.
68102 * @since 2.4
69103 */
70104 protected BufferRecycler(int bbCount, int cbCount) {
71 _byteBuffers = new byte[bbCount][];
72 _charBuffers = new char[cbCount][];
105 _byteBuffers = new AtomicReferenceArray<byte[]>(bbCount);
106 _charBuffers = new AtomicReferenceArray<char[]>(cbCount);
73107 }
74108
75109 /*
90124 if (minSize < DEF_SIZE) {
91125 minSize = DEF_SIZE;
92126 }
93 byte[] buffer = _byteBuffers[ix];
127 byte[] buffer = _byteBuffers.getAndSet(ix, null);
94128 if (buffer == null || buffer.length < minSize) {
95129 buffer = balloc(minSize);
96 } else {
97 _byteBuffers[ix] = null;
98130 }
99131 return buffer;
100132 }
101133
102134 public void releaseByteBuffer(int ix, byte[] buffer) {
103 _byteBuffers[ix] = buffer;
135 _byteBuffers.set(ix, buffer);
104136 }
105137
106138 /*
118150 if (minSize < DEF_SIZE) {
119151 minSize = DEF_SIZE;
120152 }
121 char[] buffer = _charBuffers[ix];
153 char[] buffer = _charBuffers.getAndSet(ix, null);
122154 if (buffer == null || buffer.length < minSize) {
123155 buffer = calloc(minSize);
124 } else {
125 _charBuffers[ix] = null;
126156 }
127157 return buffer;
128158 }
129159
130160 public void releaseCharBuffer(int ix, char[] buffer) {
131 _charBuffers[ix] = buffer;
161 _charBuffers.set(ix, buffer);
132162 }
133163
134164 /*
144174 protected int charBufferLength(int ix) {
145175 return CHAR_BUFFER_LENGTHS[ix];
146176 }
147
177
148178 /*
149179 /**********************************************************
150180 /* Actual allocations separated for easier debugging/profiling
00 package com.fasterxml.jackson.core.util;
11
22 import java.lang.ref.SoftReference;
3
4 import com.fasterxml.jackson.core.io.JsonStringEncoder;
53
64 /**
75 * Helper entity used to control access to simple buffer recyling scheme used for
86 * some encoding, decoding tasks.
97 *
108 * @see BufferRecycler
11 * @see JsonStringEncoder
129 *
1310 * @since 2.9.2
1411 */
9390 }
9491 return -1;
9592 }
96
97 /*
98 /**********************************************************
99 /* JsonStringEncoder
100 /**********************************************************
101 */
102
103 /**
104 * This <code>ThreadLocal</code> contains a {@link java.lang.ref.SoftReference}
105 * to a {@link BufferRecycler} used to provide a low-cost
106 * buffer recycling between reader and writer instances.
107 */
108 final protected static ThreadLocal<SoftReference<JsonStringEncoder>> _encoderRef
109 = new ThreadLocal<SoftReference<JsonStringEncoder>>();
110
111 public static JsonStringEncoder getJsonStringEncoder() {
112 SoftReference<JsonStringEncoder> ref = _encoderRef.get();
113 JsonStringEncoder enc = (ref == null) ? null : ref.get();
114
115 if (enc == null) {
116 enc = new JsonStringEncoder();
117 _encoderRef.set(new SoftReference<JsonStringEncoder>(enc));
118 }
119 return enc;
120 }
121
122 /**
123 * Helper method for encoding given String as UTF-8 encoded
124 *
125 * @since 2.9.4
126 */
127 public static byte[] encodeAsUTF8(String text) {
128 return getJsonStringEncoder().encodeAsUTF8(text);
129 }
130
131 /**
132 * @since 2.9.4
133 */
134 public static char[] quoteAsJsonText(String rawText) {
135 return getJsonStringEncoder().quoteAsString(rawText);
136 }
137
138 /**
139 * @since 2.9.4
140 */
141 public static void quoteAsJsonText(CharSequence input, StringBuilder output) {
142 getJsonStringEncoder().quoteAsString(input, output);
143 }
144
145 /**
146 * @since 2.9.4
147 */
148 public static byte[] quoteAsJsonUTF8(String rawText) {
149 return getJsonStringEncoder().quoteAsUTF8(rawText);
150 }
15193 }
3232 // Size of the first block we will allocate.
3333 private final static int INITIAL_BLOCK_SIZE = 500;
3434
35 // Maximum block size we will use for individual non-aggregated
36 // blocks. Let's limit to using 256k chunks.
37 private final static int MAX_BLOCK_SIZE = (1 << 18);
38
35 // Maximum block size we will use for individual non-aggregated blocks.
36 // For 2.10, let's limit to using 128k chunks (was 256k up to 2.9)
37 private final static int MAX_BLOCK_SIZE = (1 << 17);
38
3939 final static int DEFAULT_BLOCK_ARRAY_SIZE = 40;
4040
4141 // Optional buffer recycler instance that we can use for allocating the first block.
5656 _currBlock = (br == null) ? new byte[firstBlockSize] : br.allocByteBuffer(BufferRecycler.BYTE_WRITE_CONCAT_BUFFER);
5757 }
5858
59 private ByteArrayBuilder(BufferRecycler br, byte[] initialBlock, int initialLen) {
60 _bufferRecycler = null;
61 _currBlock = initialBlock;
62 _currBlockPtr = initialLen;
63 }
64
65 public static ByteArrayBuilder fromInitial(byte[] initialBlock, int length) {
66 return new ByteArrayBuilder(null, initialBlock, length);
67 }
68
5969 public void reset() {
6070 _pastLen = 0;
6171 _currBlockPtr = 0;
156156 }
157157
158158 /**
159 * @since 2.6.0
159 * @since 2.6
160160 */
161161 public DefaultPrettyPrinter withRootSeparator(String rootSeparator) {
162162 return withRootSeparator((rootSeparator == null) ? null : new SerializedString(rootSeparator));
251251
252252 @Override
253253 public DefaultPrettyPrinter createInstance() {
254 if (getClass() != DefaultPrettyPrinter.class) { // since 2.10
255 throw new IllegalStateException("Failed `createInstance()`: "+getClass().getName()
256 +" does not override method; it has to");
257 }
254258 return new DefaultPrettyPrinter(this);
255259 }
256260
194194
195195 @Override
196196 public void writeStartArray(int size) throws IOException { delegate.writeStartArray(size); }
197
197
198 @Override
199 public void writeStartArray(Object forValue) throws IOException { delegate.writeStartArray(forValue); }
200
201 @Override
202 public void writeStartArray(Object forValue, int size) throws IOException { delegate.writeStartArray(forValue, size); }
203
198204 @Override
199205 public void writeEndArray() throws IOException { delegate.writeEndArray(); }
200206
203209
204210 @Override
205211 public void writeStartObject(Object forValue) throws IOException { delegate.writeStartObject(forValue); }
212
213 @Override
214 public void writeStartObject(Object forValue, int size) throws IOException {
215 delegate.writeStartObject(forValue, size);
216 }
206217
207218 @Override
208219 public void writeEndObject() throws IOException { delegate.writeEndObject(); }
236236 @Override public boolean canReadTypeId() { return delegate.canReadTypeId(); }
237237 @Override public Object getObjectId() throws IOException { return delegate.getObjectId(); }
238238 @Override public Object getTypeId() throws IOException { return delegate.getTypeId(); }
239
240 /*
241 /**********************************************************
242 /* Extended API
243 /**********************************************************
244 */
245
246 /**
247 * Accessor for getting the immediate {@link JsonParser} this parser delegates calls to.
248 *
249 * @since 2.10
250 */
251 public JsonParser delegate() { return delegate; }
239252 }
2929
3030 /**
3131 * Let's start with sizable but not huge buffer, will grow as necessary
32 */
33 final static int MIN_SEGMENT_LEN = 1000;
34
35 /**
36 * Let's limit maximum segment length to something sensible
37 * like 256k
38 */
39 final static int MAX_SEGMENT_LEN = 0x40000;
32 *<p>
33 * Reduced from 1000 down to 500 in 2.10.
34 */
35 final static int MIN_SEGMENT_LEN = 500;
36
37 /**
38 * Let's limit maximum segment length to something sensible.
39 * For 2.10, let's limit to using 64kc chunks (128 kB) -- was 256kC/512kB up to 2.9
40 */
41 final static int MAX_SEGMENT_LEN = 0x10000;
4042
4143 /*
4244 /**********************************************************
119121
120122 public TextBuffer(BufferRecycler allocator) {
121123 _allocator = allocator;
124 }
125
126 /**
127 * @since 2.10
128 */
129 protected TextBuffer(BufferRecycler allocator, char[] initialSegment) {
130 _allocator = allocator;
131 _currentSegment = initialSegment;
132 _currentSize = initialSegment.length;
133 _inputStart = -1;
134 }
135
136 /**
137 * Factory method for constructing an instance with no allocator, and
138 * with initial full segment.
139 *
140 * @since 2.10
141 */
142 public static TextBuffer fromInitial(char[] initialSegment) {
143 return new TextBuffer(null, initialSegment);
122144 }
123145
124146 /**
0 // Generated 08-Mar-2019 using Moditect maven plugin
1 module com.fasterxml.jackson.core {
2 // 08-Mar-2019, tatu: Ugh. Can not use wildcards, stupid ass JDK 9+ module system...
3 // So, for 2.x core need to make sure we manually include everything.
4 // Worse, there is only syntactic validation, not contents, so we can both miss
5 // AND add bogus packages.
6 // However: at least syntax is verified; and this works with JKD8
7 exports com.fasterxml.jackson.core;
8 exports com.fasterxml.jackson.core.async;
9 exports com.fasterxml.jackson.core.base;
10 exports com.fasterxml.jackson.core.exc;
11 exports com.fasterxml.jackson.core.filter;
12 exports com.fasterxml.jackson.core.format;
13 exports com.fasterxml.jackson.core.io;
14 exports com.fasterxml.jackson.core.json;
15 exports com.fasterxml.jackson.core.json.async;
16 exports com.fasterxml.jackson.core.sym;
17 exports com.fasterxml.jackson.core.type;
18 exports com.fasterxml.jackson.core.util;
19 }
301301
302302 /*
303303 /**********************************************************
304 /* Parser/generator construction
304 /* Parser construction
305305 /**********************************************************
306306 */
307307
397397
398398 /*
399399 /**********************************************************
400 /* Generator construction
401 /**********************************************************
402 */
403
404 protected JsonGenerator createGenerator(OutputStream out) throws IOException {
405 return createGenerator(JSON_FACTORY, out);
406 }
407
408 protected JsonGenerator createGenerator(TokenStreamFactory f, OutputStream out) throws IOException {
409 return f.createGenerator(out);
410 }
411
412 protected JsonGenerator createGenerator(Writer w) throws IOException {
413 return createGenerator(JSON_FACTORY, w);
414 }
415
416 protected JsonGenerator createGenerator(TokenStreamFactory f, Writer w) throws IOException {
417 return f.createGenerator(w);
418 }
419
420 /*
421 /**********************************************************
400422 /* Helper read/write methods
401423 /**********************************************************
402424 */
403
425
404426 protected void writeJsonDoc(JsonFactory f, String doc, Writer w) throws IOException
405427 {
406428 writeJsonDoc(f, doc, f.createGenerator(w));
565587 protected JsonFactory newStreamFactory() {
566588 return new JsonFactory();
567589 }
568
590
591 // @since 2.9.8
592 protected JsonFactoryBuilder streamFactoryBuilder() {
593 return (JsonFactoryBuilder) JsonFactory.builder();
594 }
595
569596 protected String fieldNameFor(int index)
570597 {
571598 StringBuilder sb = new StringBuilder(16);
8181
8282 public void testEmpty()
8383 {
84 assertSame(JsonPointer.EMPTY, JsonPointer.empty());
85 assertSame(JsonPointer.EMPTY, JsonPointer.compile(""));
86 }
87
88 public void testEmptyName()
89 {
8490 // note: this is acceptable, to match property in '{"":3}', for example
8591 // and NOT same as what empty point, "", is.
8692 JsonPointer ptr = JsonPointer.compile("/");
8793 assertNotNull(ptr);
8894 assertNotSame(JsonPointer.EMPTY, ptr);
95
8996 assertEquals("/", ptr.toString());
97 }
98
99 // mostly for test coverage, really...
100 public void testEquality() {
101 assertFalse(JsonPointer.empty().equals(JsonPointer.compile("/")));
102
103 assertEquals(JsonPointer.compile("/foo/3"), JsonPointer.compile("/foo/3"));
104 assertFalse(JsonPointer.empty().equals(JsonPointer.compile("/12")));
105 assertFalse(JsonPointer.compile("/12").equals(JsonPointer.empty()));
106
107 // expr != String
108 assertFalse(JsonPointer.empty().equals("/"));
109 }
110
111 public void testProperties() {
112 assertTrue(JsonPointer.compile("/foo").mayMatchProperty());
113 assertFalse(JsonPointer.compile("/foo").mayMatchElement());
114
115 assertTrue(JsonPointer.compile("/12").mayMatchElement());
116 // Interestingly enough, since Json Pointer is just String, could
117 // ALSO match property with name "12"
118 assertTrue(JsonPointer.compile("/12").mayMatchProperty());
90119 }
91120
92121 public void testAppend()
7373 // for [jackson-core#356]
7474 public void testDisableSourceInclusion() throws Exception
7575 {
76 JsonFactory f = new JsonFactory();
77 f.disable(JsonParser.Feature.INCLUDE_SOURCE_IN_LOCATION);
76 JsonFactory f = JsonFactory.builder()
77 .disable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION)
78 .build();
7879
7980 JsonParser p = f.createParser("[ foobar ]");
8081 assertToken(JsonToken.START_ARRAY, p.nextToken());
1616 CharsToNameCanonicalizer.createRoot());
1717 assertVersion(jp.version());
1818 jp.close();
19 JsonGenerator jgen = new WriterBasedJsonGenerator(getIOContext(), 0, null, null);
19 JsonGenerator jgen = new WriterBasedJsonGenerator(getIOContext(), 0, null, null, '"');
2020 assertVersion(jgen.version());
2121 jgen.close();
2222 }
00 package com.fasterxml.jackson.core.base64;
1
2 import java.util.Arrays;
13
24 import org.junit.Assert;
35
7577
7678 public void testConvenienceMethods() throws Exception
7779 {
78 Base64Variant std = Base64Variants.MIME;
80 final Base64Variant std = Base64Variants.MIME;
7981
8082 byte[] input = new byte[] { 1, 2, 34, 127, -1 };
8183 String encoded = std.encode(input, false);
9395 Assert.assertArrayEquals(input, decoded);
9496 decoded = std.decode(encoded + "\n");
9597 Assert.assertArrayEquals(input, decoded);
98 }
99
100 public void testConvenienceMethodWithLFs() throws Exception
101 {
102 final Base64Variant std = Base64Variants.MIME;
103
104 final int length = 100;
105 final byte[] data = new byte[length];
106 Arrays.fill(data, (byte) 1);
107
108 final StringBuilder sb = new StringBuilder(140);
109 for (int i = 0; i < 100/3; ++i) {
110 sb.append("AQEB");
111 if (sb.length() == 76) {
112 sb.append("##");
113 }
114 }
115 sb.append("AQ==");
116 final String exp = sb.toString();
117
118 // first, JSON standard
119 assertEquals(exp.replace("##", "\\n"), std.encode(data, false));
120
121 // then with custom linefeed
122
123 assertEquals(exp.replace("##", "<%>"), std.encode(data, false, "<%>"));
96124 }
97125
98126 @SuppressWarnings("unused")
55 import static org.junit.Assert.*;
66
77 import com.fasterxml.jackson.core.*;
8 import com.fasterxml.jackson.core.util.BufferRecyclers;
98
109 public class TestJsonStringEncoder
1110 extends com.fasterxml.jackson.core.BaseTest
2423 StringBuilder output = new StringBuilder();
2524 StringBuilder builder = new StringBuilder();
2625 builder.append("foobar");
27 BufferRecyclers.quoteAsJsonText(builder, output);
26 JsonStringEncoder.getInstance().quoteAsString(builder, output);
2827 assertEquals("foobar", output.toString());
2928 builder.setLength(0);
3029 output.setLength(0);
3130 builder.append("\"x\"");
32 BufferRecyclers.quoteAsJsonText(builder, output);
31 JsonStringEncoder.getInstance().quoteAsString(builder, output);
3332 assertEquals("\\\"x\\\"", output.toString());
3433 }
3534
6160 sb2.append("\\\"");
6261 }
6362 String exp = sb2.toString();
64 BufferRecyclers.quoteAsJsonText(input, output);
63 JsonStringEncoder.getInstance().quoteAsString(input, output);
6564 assertEquals(2*input.length(), output.length());
6665 assertEquals(exp, output.toString());
6766
107106 public void testCtrlChars() throws Exception
108107 {
109108 char[] input = new char[] { 0, 1, 2, 3, 4 };
110 char[] quoted = BufferRecyclers.quoteAsJsonText(new String(input));
109 char[] quoted = JsonStringEncoder.getInstance().quoteAsString(new String(input));
111110 assertEquals("\\u0000\\u0001\\u0002\\u0003\\u0004", new String(quoted));
112111 }
113112
118117 StringBuilder builder = new StringBuilder();
119118 builder.append(input);
120119 StringBuilder output = new StringBuilder();
121 BufferRecyclers.quoteAsJsonText(builder, output);
120 JsonStringEncoder.getInstance().quoteAsString(builder, output);
122121 assertEquals("\\u0000\\u0001\\u0002\\u0003\\u0004", output.toString());
123122 }
124123
0 package com.fasterxml.jackson.core.json;
1
2 import java.io.*;
3
4 import com.fasterxml.jackson.core.*;
5
6 // For [core#549], ability to use alternate quote characters
7 public class CustomQuoteCharTest
8 extends com.fasterxml.jackson.core.BaseTest
9 {
10 final JsonFactory JSON_F = streamFactoryBuilder()
11 .quoteChar('\'')
12 .build();
13
14 // Only ASCII range supported as of 2.10
15 public void testInvalidQuote() throws Exception
16 {
17 try {
18 streamFactoryBuilder()
19 .quoteChar('\u00A0');
20 fail("Should not allow quote character outside ASCII range");
21 } catch (IllegalArgumentException e) {
22 verifyException(e, "Can only use Unicode characters up to 0x7F");
23 }
24 }
25
26 public void testBasicAposWithCharBased() throws Exception
27 {
28 StringWriter w;
29 JsonGenerator g;
30
31 // with Object
32 w = new StringWriter();
33 g = createGenerator(JSON_F, w);
34 _writeObject(g, "question", "answer");
35 g.close();
36 assertEquals("{'question':'answer'}", w.toString());
37
38 // with Array
39 w = new StringWriter();
40 g = createGenerator(JSON_F, w);
41 _writeArray(g, "hello world");
42 g.close();
43 assertEquals("['hello world']", w.toString());
44 }
45
46 public void testBasicAposWithByteBased() throws Exception
47 {
48 ByteArrayOutputStream out;
49 JsonGenerator g;
50
51 // with Object
52 out = new ByteArrayOutputStream();
53 g = createGenerator(JSON_F, out);
54 _writeObject(g, "question", "answer");
55 g.close();
56 assertEquals("{'question':'answer'}", out.toString("UTF-8"));
57
58 // with Array
59 out = new ByteArrayOutputStream();
60 g = createGenerator(JSON_F, out);
61 _writeArray(g, "hello world");
62 g.close();
63 assertEquals("['hello world']", out.toString("UTF-8"));
64 }
65
66 public void testAposQuotingWithCharBased() throws Exception
67 {
68 StringWriter w;
69 JsonGenerator g;
70
71 // with Object
72 w = new StringWriter();
73 g = createGenerator(JSON_F, w);
74 _writeObject(g, "key", "It's \"fun\"");
75 g.close();
76 // should escape apostrophes but not quotes?
77 assertEquals("{'key':'It\\u0027s \\\"fun\\\"'}", w.toString());
78
79 // with Array
80 w = new StringWriter();
81 g = createGenerator(JSON_F, w);
82 _writeArray(g, "It's a sin");
83 g.close();
84 assertEquals("['It\\u0027s a sin']", w.toString());
85 }
86
87 public void testAposQuotingWithByteBased() throws Exception
88 {
89 ByteArrayOutputStream out;
90 JsonGenerator g;
91
92 // with Object
93 out = new ByteArrayOutputStream();
94 g = createGenerator(JSON_F, out);
95 _writeObject(g, "key", "It's \"fun\"");
96 g.close();
97 // should escape apostrophes but not quotes?
98 assertEquals("{'key':'It\\u0027s \\\"fun\\\"'}", out.toString("UTF-8"));
99
100 // with Array
101 out = new ByteArrayOutputStream();
102 g = createGenerator(JSON_F, out);
103 _writeArray(g, "It's a sin");
104 g.close();
105 assertEquals("['It\\u0027s a sin']", out.toString("UTF-8"));
106 }
107
108 private void _writeObject(JsonGenerator g, String key, String value) throws Exception {
109 g.writeStartObject();
110 g.writeStringField(key, value);
111 g.writeEndObject();
112 }
113
114 private void _writeArray(JsonGenerator g, String value) throws Exception {
115 g.writeStartArray();
116 g.writeString(value);
117 g.writeEndArray();
118 }
119 }
1414 {
1515 private final JsonFactory JSON_F = new JsonFactory();
1616
17 @SuppressWarnings("deprecation")
1718 public void testConfigDefaults() throws IOException
1819 {
1920 JsonGenerator g = JSON_F.createGenerator(new StringWriter());
2021 assertFalse(g.isEnabled(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS));
22
2123 assertFalse(g.isEnabled(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN));
24 assertFalse(g.isEnabled(StreamWriteFeature.WRITE_BIGDECIMAL_AS_PLAIN));
2225
2326 assertTrue(g.canOmitFields());
2427 assertFalse(g.canWriteBinaryNatively());
3942 g.overrideStdFeatures(mask, mask);
4043 assertTrue(g.isEnabled(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS));
4144 assertTrue(g.isEnabled(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN));
45 assertTrue(g.isEnabled(StreamWriteFeature.WRITE_BIGDECIMAL_AS_PLAIN));
4246
4347 // and for now, also test straight override
4448 g.setFeatureMask(0);
4549 assertFalse(g.isEnabled(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS));
4650 assertFalse(g.isEnabled(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN));
51 assertFalse(g.isEnabled(StreamWriteFeature.WRITE_BIGDECIMAL_AS_PLAIN));
4752 g.close();
4853 }
4954
5358 // by default, quoting should be enabled
5459 _testFieldNameQuoting(f, true);
5560 // can disable it
56 f.disable(JsonGenerator.Feature.QUOTE_FIELD_NAMES);
61 f = JsonFactory.builder()
62 .disable(JsonWriteFeature.QUOTE_FIELD_NAMES)
63 .build();
5764 _testFieldNameQuoting(f, false);
5865 // and (re)enable:
59 f.enable(JsonGenerator.Feature.QUOTE_FIELD_NAMES);
66 f = JsonFactory.builder()
67 .enable(JsonWriteFeature.QUOTE_FIELD_NAMES)
68 .build();
6069 _testFieldNameQuoting(f, true);
6170 }
6271
6675 // by default, quoting should be enabled
6776 _testNonNumericQuoting(f, true);
6877 // can disable it
69 f.disable(JsonGenerator.Feature.QUOTE_NON_NUMERIC_NUMBERS);
78 f = JsonFactory.builder()
79 .disable(JsonWriteFeature.WRITE_NAN_AS_STRINGS)
80 .build();
7081 _testNonNumericQuoting(f, false);
7182 // and (re)enable:
72 f.enable(JsonGenerator.Feature.QUOTE_NON_NUMERIC_NUMBERS);
83 f = JsonFactory.builder()
84 .enable(JsonWriteFeature.WRITE_NAN_AS_STRINGS)
85 .build();
7386 _testNonNumericQuoting(f, true);
7487 }
7588
8497 assertEquals("[1,2,1.25,2.25,3001,0.5,-1]", _writeNumbers(f));
8598
8699 // but if overridden, quotes as Strings
87 f.configure(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS, true);
100 f = JsonFactory.builder()
101 .enable(JsonWriteFeature.WRITE_NUMBERS_AS_STRINGS)
102 .build();
88103 assertEquals("[\"1\",\"2\",\"1.25\",\"2.25\",\"3001\",\"0.5\",\"-1\"]",
89104 _writeNumbers(f));
90105
112127
113128 public void testBigDecimalAsPlainString() throws Exception
114129 {
115 JsonFactory f = new JsonFactory();
116130 BigDecimal ENG = new BigDecimal("1E+2");
117 f.enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN);
118 f.enable(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS);
131 JsonFactory f = JsonFactory.builder()
132 .enable(StreamWriteFeature.WRITE_BIGDECIMAL_AS_PLAIN)
133 .enable(JsonWriteFeature.WRITE_NUMBERS_AS_STRINGS)
134 .build();
119135
120136 StringWriter sw = new StringWriter();
121137 JsonGenerator g = f.createGenerator(sw);
132148 }
133149
134150 // [core#315]
151 @SuppressWarnings("deprecation")
135152 public void testTooBigBigDecimal() throws Exception
136153 {
137154 JsonFactory f = new JsonFactory();
220237
221238 // // Then with alternatively configured factory
222239
223 JsonFactory f2 = new JsonFactory();
224 f2.disable(JsonGenerator.Feature.QUOTE_FIELD_NAMES);
240 JsonFactory f2 = JsonFactory.builder()
241 .disable(JsonWriteFeature.QUOTE_FIELD_NAMES)
242 .build();
225243
226244 _testFieldNameQuotingEnabled(f2, true, true, "{\"foo\":1}");
227245 _testFieldNameQuotingEnabled(f2, false, true, "{\"foo\":1}");
231249 _testFieldNameQuotingEnabled(f2, false, false, "{foo:1}");
232250 }
233251
252 @SuppressWarnings("deprecation")
234253 private void _testFieldNameQuotingEnabled(JsonFactory f, boolean useBytes,
235254 boolean useQuotes, String exp) throws IOException
236255 {
253272 assertEquals(exp, json);
254273 }
255274
275 @SuppressWarnings("deprecation")
256276 public void testChangeOnGenerator() throws IOException
257277 {
258278 StringWriter w = new StringWriter();
1919 }
2020
2121 @Override
22 public <T> T readValue(JsonParser p, TypeReference<?> valueTypeRef) throws IOException {
22 public <T> T readValue(JsonParser p, TypeReference<T> valueTypeRef) throws IOException {
2323 return null;
2424 }
2525
3434 }
3535
3636 @Override
37 public <T> Iterator<T> readValues(JsonParser p, TypeReference<?> valueTypeRef) throws IOException {
37 public <T> Iterator<T> readValues(JsonParser p, TypeReference<T> valueTypeRef) throws IOException {
3838 return null;
3939 }
4040
7373
7474 @Override
7575 public <T> T treeToValue(TreeNode n, Class<T> valueType) throws JsonProcessingException {
76 return null;
77 }
78
79 @Override
80 public TreeNode missingNode() {
81 return null;
82 }
83
84 @Override
85 public TreeNode nullNode() {
7686 return null;
7787 }
7888 }
91101 /**********************************************************************
92102 */
93103
104 @SuppressWarnings("deprecation")
94105 public void testGeneratorFeatures() throws Exception
95106 {
96107 JsonFactory f = new JsonFactory();
97108 assertNull(f.getCodec());
98109
99 f.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, true);
110 f = JsonFactory.builder()
111 .configure(JsonWriteFeature.QUOTE_FIELD_NAMES, true)
112 .build();
113 // 24-Oct-2018, tatu: Until 3.x, we'll only have backwards compatible
100114 assertTrue(f.isEnabled(JsonGenerator.Feature.QUOTE_FIELD_NAMES));
101 f.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, false);
115 f = JsonFactory.builder()
116 .configure(JsonWriteFeature.QUOTE_FIELD_NAMES, false)
117 .build();
102118 assertFalse(f.isEnabled(JsonGenerator.Feature.QUOTE_FIELD_NAMES));
103119 }
104120
105121 public void testFactoryFeatures() throws Exception
106122 {
107 JsonFactory f = new JsonFactory();
108
109 f.configure(JsonFactory.Feature.INTERN_FIELD_NAMES, true);
110 assertTrue(f.isEnabled(JsonFactory.Feature.INTERN_FIELD_NAMES));
111 f.configure(JsonFactory.Feature.INTERN_FIELD_NAMES, false);
123 JsonFactory f = JsonFactory.builder()
124 .configure(JsonFactory.Feature.INTERN_FIELD_NAMES, false)
125 .build();
112126 assertFalse(f.isEnabled(JsonFactory.Feature.INTERN_FIELD_NAMES));
113127
114128 // by default, should be enabled
115129 assertTrue(f.isEnabled(JsonFactory.Feature.USE_THREAD_LOCAL_FOR_BUFFER_RECYCLING));
116 f.configure(JsonFactory.Feature.USE_THREAD_LOCAL_FOR_BUFFER_RECYCLING, false);
117 assertFalse(f.isEnabled(JsonFactory.Feature.USE_THREAD_LOCAL_FOR_BUFFER_RECYCLING));
118130 }
119131
120132 // for [core#189]: verify that it's ok to disable recycling
123135 // disables this handling otherwise
124136 public void testDisablingBufferRecycling() throws Exception
125137 {
126 JsonFactory f = new JsonFactory();
127
128 f.disable(JsonFactory.Feature.USE_THREAD_LOCAL_FOR_BUFFER_RECYCLING);
138 JsonFactory f = JsonFactory.builder()
139 .disable(JsonFactory.Feature.USE_THREAD_LOCAL_FOR_BUFFER_RECYCLING)
140 .build();
141 assertFalse(f.isEnabled(JsonFactory.Feature.USE_THREAD_LOCAL_FOR_BUFFER_RECYCLING));
129142
130143 // First, generation
131144 for (int i = 0; i < 3; ++i) {
195208 }
196209
197210 // #72
211 @SuppressWarnings("deprecation")
198212 public void testCopy() throws Exception
199213 {
200214 JsonFactory jf = new JsonFactory();
205219 assertFalse(jf.isEnabled(JsonGenerator.Feature.ESCAPE_NON_ASCII));
206220
207221 // then change, verify that changes "stick"
208 jf.disable(JsonFactory.Feature.INTERN_FIELD_NAMES);
209 jf.enable(JsonParser.Feature.ALLOW_COMMENTS);
210 jf.enable(JsonGenerator.Feature.ESCAPE_NON_ASCII);
222 jf = JsonFactory.builder()
223 .disable(JsonFactory.Feature.INTERN_FIELD_NAMES)
224 .enable(JsonReadFeature.ALLOW_JAVA_COMMENTS)
225 .enable(JsonWriteFeature.ESCAPE_NON_ASCII)
226 .build();
211227 ObjectCodec codec = new BogusCodec();
212228 jf.setCodec(codec);
213229
+0
-66
src/test/java/com/fasterxml/jackson/core/json/LocationInArrayTest.java less more
0 package com.fasterxml.jackson.core.json;
1
2 import com.fasterxml.jackson.core.*;
3
4 // Tests mostly for [core#229]
5 public class LocationInArrayTest extends com.fasterxml.jackson.core.BaseTest
6 {
7 final JsonFactory JSON_F = new JsonFactory();
8
9 // for [core#229]
10 public void testOffsetInArraysBytes() throws Exception {
11 _testOffsetInArrays(true);
12 }
13
14 // for [core#229]
15 public void testOffsetInArraysChars() throws Exception {
16 _testOffsetInArrays(false);
17 }
18
19 private void _testOffsetInArrays(boolean useBytes) throws Exception
20 {
21 JsonParser p;
22 final String DOC = " [10, 251,\n 3 ]";
23
24 // first, char based:
25 p = useBytes ? JSON_F.createParser(DOC.getBytes("UTF-8"))
26 : JSON_F.createParser(DOC.toCharArray());
27 assertToken(JsonToken.START_ARRAY, p.nextToken());
28 _assertLocation(useBytes, p.getTokenLocation(), 2L, 1, 3);
29 _assertLocation(useBytes, p.getCurrentLocation(), 3L, 1, 4);
30
31 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
32 _assertLocation(useBytes, p.getTokenLocation(), 3L, 1, 4);
33 assertEquals(10, p.getIntValue()); // just to ensure read proceeds to end
34 // 2-digits so
35 _assertLocation(useBytes, p.getCurrentLocation(), 5L, 1, 6);
36
37 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
38 _assertLocation(useBytes, p.getTokenLocation(), 7L, 1, 8);
39 assertEquals(251, p.getIntValue()); // just to ensure read proceeds to end
40 _assertLocation(useBytes, p.getCurrentLocation(), 10L, 1, 11);
41
42 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
43 _assertLocation(useBytes, p.getTokenLocation(), 15L, 2, 4);
44 assertEquals(3, p.getIntValue());
45 _assertLocation(useBytes, p.getCurrentLocation(), 16L, 2, 5);
46
47 assertToken(JsonToken.END_ARRAY, p.nextToken());
48 _assertLocation(useBytes, p.getTokenLocation(), 18L, 2, 7);
49 _assertLocation(useBytes, p.getCurrentLocation(), 19L, 2, 8);
50
51 p.close();
52 }
53
54 private void _assertLocation(boolean useBytes, JsonLocation loc, long offset, int row, int col)
55 {
56 assertEquals(row, loc.getLineNr());
57 assertEquals(col, loc.getColumnNr());
58
59 if (useBytes) {
60 assertEquals(offset, loc.getByteOffset());
61 } else {
62 assertEquals(offset, loc.getCharOffset());
63 }
64 }
65 }
+0
-99
src/test/java/com/fasterxml/jackson/core/json/LocationInObjectTest.java less more
0 package com.fasterxml.jackson.core.json;
1
2 import com.fasterxml.jackson.core.*;
3
4 // tests for [core#37]
5 public class LocationInObjectTest extends BaseTest
6 {
7 public void testOffsetWithObjectFieldsUsingUTF8() throws Exception
8 {
9 final JsonFactory f = new JsonFactory();
10 byte[] b = "{\"f1\":\"v1\",\"f2\":{\"f3\":\"v3\"},\"f4\":[true,false],\"f5\":5}".getBytes("UTF-8");
11 // 1 6 11 16 17 22 28 33 34 39 46 51
12 JsonParser p = f.createParser(b);
13
14 assertEquals(JsonToken.START_OBJECT, p.nextToken());
15
16 assertEquals(JsonToken.FIELD_NAME, p.nextToken());
17 assertEquals(1L, p.getTokenLocation().getByteOffset());
18 assertEquals(JsonToken.VALUE_STRING, p.nextToken());
19 assertEquals(6L, p.getTokenLocation().getByteOffset());
20
21 assertEquals("f2", p.nextFieldName());
22 assertEquals(11L, p.getTokenLocation().getByteOffset());
23 assertEquals(JsonToken.START_OBJECT, p.nextValue());
24 assertEquals(16L, p.getTokenLocation().getByteOffset());
25
26 assertEquals("f3", p.nextFieldName());
27 assertEquals(17L, p.getTokenLocation().getByteOffset());
28 assertEquals(JsonToken.VALUE_STRING, p.nextValue());
29 assertEquals(22L, p.getTokenLocation().getByteOffset());
30 assertEquals(JsonToken.END_OBJECT, p.nextToken());
31
32 assertEquals("f4", p.nextFieldName());
33 assertEquals(28L, p.getTokenLocation().getByteOffset());
34 assertEquals(JsonToken.START_ARRAY, p.nextValue());
35 assertEquals(33L, p.getTokenLocation().getByteOffset());
36
37 assertEquals(JsonToken.VALUE_TRUE, p.nextValue());
38 assertEquals(34L, p.getTokenLocation().getByteOffset());
39
40 assertEquals(JsonToken.VALUE_FALSE, p.nextValue());
41 assertEquals(39L, p.getTokenLocation().getByteOffset());
42 assertEquals(JsonToken.END_ARRAY, p.nextToken());
43
44 assertEquals("f5", p.nextFieldName());
45 assertEquals(46L, p.getTokenLocation().getByteOffset());
46 assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken());
47 assertEquals(51L, p.getTokenLocation().getByteOffset());
48 assertEquals(JsonToken.END_OBJECT, p.nextToken());
49
50 p.close();
51 }
52
53 public void testOffsetWithObjectFieldsUsingReader() throws Exception
54 {
55 final JsonFactory f = new JsonFactory();
56 char[] c = "{\"f1\":\"v1\",\"f2\":{\"f3\":\"v3\"},\"f4\":[true,false],\"f5\":5}".toCharArray();
57 // 1 6 11 16 17 22 28 33 34 39 46 51
58 JsonParser p = f.createParser(c);
59
60 assertEquals(JsonToken.START_OBJECT, p.nextToken());
61
62 assertEquals(JsonToken.FIELD_NAME, p.nextToken());
63 assertEquals(1L, p.getTokenLocation().getCharOffset());
64 assertEquals(JsonToken.VALUE_STRING, p.nextToken());
65 assertEquals(6L, p.getTokenLocation().getCharOffset());
66
67 assertEquals("f2", p.nextFieldName());
68 assertEquals(11L, p.getTokenLocation().getCharOffset());
69 assertEquals(JsonToken.START_OBJECT, p.nextValue());
70 assertEquals(16L, p.getTokenLocation().getCharOffset());
71
72 assertEquals("f3", p.nextFieldName());
73 assertEquals(17L, p.getTokenLocation().getCharOffset());
74 assertEquals(JsonToken.VALUE_STRING, p.nextValue());
75 assertEquals(22L, p.getTokenLocation().getCharOffset());
76 assertEquals(JsonToken.END_OBJECT, p.nextToken());
77
78 assertEquals("f4", p.nextFieldName());
79 assertEquals(28L, p.getTokenLocation().getCharOffset());
80 assertEquals(JsonToken.START_ARRAY, p.nextValue());
81 assertEquals(33L, p.getTokenLocation().getCharOffset());
82
83 assertEquals(JsonToken.VALUE_TRUE, p.nextValue());
84 assertEquals(34L, p.getTokenLocation().getCharOffset());
85
86 assertEquals(JsonToken.VALUE_FALSE, p.nextValue());
87 assertEquals(39L, p.getTokenLocation().getCharOffset());
88 assertEquals(JsonToken.END_ARRAY, p.nextToken());
89
90 assertEquals("f5", p.nextFieldName());
91 assertEquals(46L, p.getTokenLocation().getCharOffset());
92 assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken());
93 assertEquals(51L, p.getTokenLocation().getCharOffset());
94 assertEquals(JsonToken.END_OBJECT, p.nextToken());
95
96 p.close();
97 }
98 }
+0
-81
src/test/java/com/fasterxml/jackson/core/json/LocationOffsetsTest.java less more
0 package com.fasterxml.jackson.core.json;
1
2 import com.fasterxml.jackson.core.*;
3
4 // NOTE: just a stub so for, fill me!
5 public class LocationOffsetsTest extends com.fasterxml.jackson.core.BaseTest
6 {
7 final JsonFactory JSON_F = new JsonFactory();
8
9 // Trivially simple unit test for basics wrt offsets
10 public void testSimpleInitialOffsets() throws Exception
11 {
12 JsonLocation loc;
13 JsonParser p;
14 final String DOC = "{ }";
15
16 // first, char based:
17 p = JSON_F.createParser(DOC);
18 assertToken(JsonToken.START_OBJECT, p.nextToken());
19
20 loc = p.getTokenLocation();
21 assertEquals(-1L, loc.getByteOffset());
22 assertEquals(0L, loc.getCharOffset());
23 assertEquals(1, loc.getLineNr());
24 assertEquals(1, loc.getColumnNr());
25
26 loc = p.getCurrentLocation();
27 assertEquals(-1L, loc.getByteOffset());
28 assertEquals(1L, loc.getCharOffset());
29 assertEquals(1, loc.getLineNr());
30 assertEquals(2, loc.getColumnNr());
31
32 p.close();
33
34 // then byte-based
35
36 p = JSON_F.createParser(DOC.getBytes("UTF-8"));
37 assertToken(JsonToken.START_OBJECT, p.nextToken());
38
39 loc = p.getTokenLocation();
40 assertEquals(0L, loc.getByteOffset());
41 assertEquals(-1L, loc.getCharOffset());
42 assertEquals(1, loc.getLineNr());
43 assertEquals(1, loc.getColumnNr());
44
45 loc = p.getCurrentLocation();
46 assertEquals(1L, loc.getByteOffset());
47 assertEquals(-1L, loc.getCharOffset());
48 assertEquals(1, loc.getLineNr());
49 assertEquals(2, loc.getColumnNr());
50
51 p.close();
52 }
53
54 // for [core#111]
55 public void testOffsetWithInputOffset() throws Exception
56 {
57 JsonLocation loc;
58 JsonParser p;
59 // 3 spaces before, 2 after, just for padding
60 byte[] b = " { } ".getBytes("UTF-8");
61
62 // and then peel them off
63 p = JSON_F.createParser(b, 3, b.length-5);
64 assertToken(JsonToken.START_OBJECT, p.nextToken());
65
66 loc = p.getTokenLocation();
67 assertEquals(0L, loc.getByteOffset());
68 assertEquals(-1L, loc.getCharOffset());
69 assertEquals(1, loc.getLineNr());
70 assertEquals(1, loc.getColumnNr());
71
72 loc = p.getCurrentLocation();
73 assertEquals(1L, loc.getByteOffset());
74 assertEquals(-1L, loc.getCharOffset());
75 assertEquals(1, loc.getLineNr());
76 assertEquals(2, loc.getColumnNr());
77
78 p.close();
79 }
80 }
11
22 import com.fasterxml.jackson.core.*;
33
4 import java.io.ByteArrayOutputStream;
5 import java.io.StringReader;
6 import java.io.StringWriter;
4 import java.io.*;
75 import java.util.Random;
86
97 /**
273271 assertEquals(JsonToken.END_ARRAY, p.currentToken());
274272 p.close();
275273 }
274
275 // [jackson-core#556]
276 public void testIssue556() throws Exception
277 {
278 StringBuilder sb = new StringBuilder(8000);
279 sb.append('"');
280 for (int i = 0; i < 7988; i++) {
281 sb.append("a");
282 }
283 sb.append('"');
284 JsonGenerator g = FACTORY.createGenerator(new ByteArrayOutputStream());
285
286 g.writeStartArray();
287 _write556(g, sb.toString());
288 _write556(g, "b");
289 _write556(g, "c");
290 g.writeEndArray();
291 g.close();
292 }
293
294 private void _write556(JsonGenerator g, String value) throws Exception
295 {
296 g.writeString(new StringReader(value), -1);
297 }
276298 }
1111 public class TestCharEscaping
1212 extends com.fasterxml.jackson.core.BaseTest
1313 {
14 // for [JACKSON-627]
1514 @SuppressWarnings("serial")
1615 private final static CharacterEscapes ESC_627 = new CharacterEscapes() {
1716 final int[] ascii = CharacterEscapes.standardAsciiEscapesForJSON();
3635 /* Unit tests
3736 /**********************************************************
3837 */
38
39 private final static JsonFactory JSON_F = new JsonFactory();
3940
4041 public void testMissingEscaping()
4142 throws Exception
131132 jp.close();
132133 }
133134
134 // for [JACKSON-627]
135135 public void testWriteLongCustomEscapes() throws Exception
136136 {
137137 JsonFactory jf = new JsonFactory();
149149 jgen.close();
150150 }
151151
152 // [Issue#116]
152 // [jackson-core#116]
153153 public void testEscapesForCharArrays() throws Exception {
154 JsonFactory jf = new JsonFactory();
155154 StringWriter writer = new StringWriter();
156 JsonGenerator jgen = jf.createGenerator(writer);
155 JsonGenerator jgen = JSON_F.createGenerator(writer);
157156 // must call #writeString(char[],int,int) and not #writeString(String)
158157 jgen.writeString(new char[] { '\0' }, 0, 1);
159158 jgen.close();
160159 assertEquals("\"\\u0000\"", writer.toString());
161160 }
161
162 // [jackson-core#540]
163 public void testInvalidEscape() throws Exception {
164 JsonParser p = JSON_F.createParser(quote("\\u\u0080...").getBytes("UTF-8"));
165 assertToken(JsonToken.VALUE_STRING, p.nextToken());
166 // this is where we should get proper exception
167 try {
168 p.getText();
169 fail("Should not pass");
170 } catch (JsonParseException e) {
171 verifyException(e, "Unexpected character");
172 }
173 p.close();
174 }
175
176 // [jackson-core#116]
177 public void testEscapeNonLatin1Chars() throws Exception {
178 _testEscapeNonLatin1ViaChars(false);
179 }
180
181 // [jackson-core#116]
182 public void testEscapeNonLatin1Bytes() throws Exception {
183 _testEscapeNonLatin1ViaChars(true);
184 }
185
186 private void _testEscapeNonLatin1ViaChars(boolean useBytes) throws Exception {
187 // NOTE! First one is outside latin-1, so escape; second one within, do NOT escape:
188 final String VALUE_IN = "Line\u2028feed, \u00D6l!";
189 final String VALUE_ESCAPED = "Line\\u2028feed, \u00D6l!";
190 final JsonFactory DEFAULT_F = new JsonFactory();
191
192 // First: with default settings, no auto-escaping
193 _testEscapeNonLatin1(DEFAULT_F, VALUE_IN, VALUE_IN, useBytes); // char
194
195 // Second: with escaping beyond Latin-1 range
196 final JsonFactory latinF = ((JsonFactoryBuilder)JsonFactory.builder())
197 .highestNonEscapedChar(255)
198 .build();
199 _testEscapeNonLatin1(latinF, VALUE_IN, VALUE_ESCAPED, useBytes);
200 }
201
202 private void _testEscapeNonLatin1(JsonFactory f, String valueIn, String expEncoded,
203 boolean useBytes) throws Exception
204 {
205 ByteArrayOutputStream bytes = new ByteArrayOutputStream();
206 StringWriter sw = new StringWriter();
207 final JsonGenerator g = useBytes ? f.createGenerator(bytes, JsonEncoding.UTF8)
208 : f.createGenerator(sw);
209 g.writeStartArray();
210 g.writeString(valueIn);
211 g.writeEndArray();
212 g.close();
213
214 // Don't parse, as we want to verify actual escaping aspects
215
216 final String doc = useBytes ? bytes.toString("UTF-8") : sw.toString();
217 assertEquals("[\""+expEncoded+"\"]", doc);
218 }
162219 }
163
127127 /********************************************************
128128 */
129129
130 @SuppressWarnings("resource")
130 @SuppressWarnings({ "resource", "deprecation" })
131131 private void _testEscapeAboveAscii(boolean useStream) throws Exception
132132 {
133133 JsonFactory f = new JsonFactory();
7070
7171 public void testInputDecoration() throws IOException
7272 {
73 JsonFactory f = new JsonFactory();
74 f.setInputDecorator(new SimpleInputDecorator());
75 JsonParser jp;
73 JsonFactory f = JsonFactory.builder()
74 .inputDecorator(new SimpleInputDecorator())
75 .build();
76 JsonParser p;
7677 // first test with Reader
77 jp = f.createParser(new StringReader("{ }"));
78 p = f.createParser(new StringReader("{ }"));
7879 // should be overridden;
79 assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
80 assertEquals(789, jp.getIntValue());
81 jp.close();
80 assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken());
81 assertEquals(789, p.getIntValue());
82 p.close();
8283
8384 // similarly with InputStream
84 jp = f.createParser(new ByteArrayInputStream("[ ]".getBytes("UTF-8")));
85 p = f.createParser(new ByteArrayInputStream("[ ]".getBytes("UTF-8")));
8586 // should be overridden;
86 assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
87 assertEquals(123, jp.getIntValue());
88 jp.close();
87 assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken());
88 assertEquals(123, p.getIntValue());
89 p.close();
8990
9091 // and with raw bytes
91 jp = f.createParser("[ ]".getBytes("UTF-8"));
92 p = f.createParser("[ ]".getBytes("UTF-8"));
9293 // should be overridden;
93 assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
94 assertEquals(456, jp.getIntValue());
95 jp.close();
94 assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken());
95 assertEquals(456, p.getIntValue());
96 p.close();
9697 }
9798
9899 public void testOutputDecoration() throws IOException
99100 {
100 JsonFactory f = new JsonFactory();
101 f.setOutputDecorator(new SimpleOutputDecorator());
102 JsonGenerator jg;
101 JsonFactory f = JsonFactory.builder()
102 .outputDecorator(new SimpleOutputDecorator())
103 .build();
104 JsonGenerator g;
103105
104106 StringWriter sw = new StringWriter();
105 jg = f.createGenerator(sw);
106 jg.close();
107 g = f.createGenerator(sw);
108 g.close();
107109 assertEquals("567", sw.toString());
108110
109111 ByteArrayOutputStream out = new ByteArrayOutputStream();
110 jg = f.createGenerator(out, JsonEncoding.UTF8);
111 jg.close();
112 g = f.createGenerator(out, JsonEncoding.UTF8);
113 g.close();
112114 assertEquals("123", out.toString("UTF-8"));
113115 }
114116 }
00 package com.fasterxml.jackson.core.json;
11
22 import java.io.*;
3 import java.util.Random;
34
45 import com.fasterxml.jackson.core.*;
56 import com.fasterxml.jackson.core.io.SerializedString;
1011 final static String NAME_WITH_QUOTES = "\"name\"";
1112 final static String NAME_WITH_LATIN1 = "P\u00f6ll\u00f6";
1213
14 final static String VALUE_WITH_QUOTES = "\"Value\"";
15 final static String VALUE2 = _generateLongName(9000);
16
17 private final JsonFactory JSON_F = new JsonFactory();
18
1319 private final SerializedString quotedName = new SerializedString(NAME_WITH_QUOTES);
1420 private final SerializedString latin1Name = new SerializedString(NAME_WITH_LATIN1);
1521
16 public void testSimple() throws Exception
22 public void testSimpleFieldNames() throws Exception
1723 {
18 JsonFactory jf = new JsonFactory();
19
2024 // First using char-backed generator
2125 StringWriter sw = new StringWriter();
22 JsonGenerator jgen = jf.createGenerator(sw);
23 _writeSimple(jgen);
24 jgen.close();
26 JsonGenerator gen = JSON_F.createGenerator(sw);
27 _writeSimple(gen);
28 gen.close();
2529 String json = sw.toString();
26 _verifySimple(jf.createParser(json));
30 _verifySimple(JSON_F.createParser(json));
2731
2832 // then using UTF-8
2933 ByteArrayOutputStream out = new ByteArrayOutputStream();
30 jgen = jf.createGenerator(out, JsonEncoding.UTF8);
31 _writeSimple(jgen);
32 jgen.close();
34 gen = JSON_F.createGenerator(out, JsonEncoding.UTF8);
35 _writeSimple(gen);
36 gen.close();
3337 byte[] jsonB = out.toByteArray();
34 _verifySimple(jf.createParser(jsonB));
38 _verifySimple(JSON_F.createParser(jsonB));
39 }
40
41 public void testSimpleValues() throws Exception
42 {
43 // First using char-backed generator
44 StringWriter sw = new StringWriter();
45 JsonGenerator gen = JSON_F.createGenerator(sw);
46 _writeSimpleValues(gen);
47 gen.close();
48 _verifySimpleValues(JSON_F.createParser(new StringReader(sw.toString())));
49
50 // then using UTF-8
51 ByteArrayOutputStream out = new ByteArrayOutputStream();
52 gen = JSON_F.createGenerator(out, JsonEncoding.UTF8);
53 _writeSimpleValues(gen);
54 gen.close();
55 _verifySimpleValues(JSON_F.createParser(new ByteArrayInputStream(out.toByteArray())));
3556 }
3657
3758 /*
3960 /* Helper methods
4061 /**********************************************************
4162 */
42
43 private void _writeSimple(JsonGenerator jgen) throws Exception
63
64 private void _writeSimple(JsonGenerator gen) throws Exception
4465 {
4566 // Let's just write array of 2 objects
46 jgen.writeStartArray();
67 gen.writeStartArray();
4768
48 jgen.writeStartObject();
49 jgen.writeFieldName(quotedName);
50 jgen.writeString("a");
51 jgen.writeFieldName(latin1Name);
52 jgen.writeString("b");
53 jgen.writeEndObject();
69 gen.writeStartObject();
70 gen.writeFieldName(quotedName);
71 gen.writeString("a");
72 gen.writeFieldName(latin1Name);
73 gen.writeString("b");
74 gen.writeEndObject();
5475
55 jgen.writeStartObject();
56 jgen.writeFieldName(latin1Name);
57 jgen.writeString("c");
58 jgen.writeFieldName(quotedName);
59 jgen.writeString("d");
60 jgen.writeEndObject();
76 gen.writeStartObject();
77 gen.writeFieldName(latin1Name);
78 gen.writeString("c");
79 gen.writeFieldName(quotedName);
80 gen.writeString("d");
81 gen.writeEndObject();
6182
62 jgen.writeEndArray();
83 gen.writeEndArray();
6384 }
6485
65 private void _verifySimple(JsonParser jp) throws Exception
86 private void _writeSimpleValues(JsonGenerator gen) throws Exception
6687 {
67 assertToken(JsonToken.START_ARRAY, jp.nextToken());
88 // Let's just write an array of 2 objects
89 gen.writeStartArray();
90 gen.writeStartObject();
91 gen.writeFieldName(NAME_WITH_QUOTES);
92 gen.writeString(new SerializedString(VALUE_WITH_QUOTES));
93 gen.writeFieldName(NAME_WITH_LATIN1);
94 gen.writeString(VALUE2);
95 gen.writeEndObject();
6896
69 assertToken(JsonToken.START_OBJECT, jp.nextToken());
70 assertToken(JsonToken.FIELD_NAME, jp.nextToken());
71 assertEquals(NAME_WITH_QUOTES, jp.getText());
72 assertToken(JsonToken.VALUE_STRING, jp.nextToken());
73 assertEquals("a", jp.getText());
74 assertToken(JsonToken.FIELD_NAME, jp.nextToken());
75 assertEquals(NAME_WITH_LATIN1, jp.getText());
76 assertToken(JsonToken.VALUE_STRING, jp.nextToken());
77 assertEquals("b", jp.getText());
78 assertToken(JsonToken.END_OBJECT, jp.nextToken());
97 gen.writeStartObject();
98 gen.writeFieldName(NAME_WITH_LATIN1);
99 gen.writeString(VALUE_WITH_QUOTES);
100 gen.writeFieldName(NAME_WITH_QUOTES);
101 gen.writeString(new SerializedString(VALUE2));
102 gen.writeEndObject();
79103
80 assertToken(JsonToken.START_OBJECT, jp.nextToken());
81 assertToken(JsonToken.FIELD_NAME, jp.nextToken());
82 assertEquals(NAME_WITH_LATIN1, jp.getText());
83 assertToken(JsonToken.VALUE_STRING, jp.nextToken());
84 assertEquals("c", jp.getText());
85 assertToken(JsonToken.FIELD_NAME, jp.nextToken());
86 assertEquals(NAME_WITH_QUOTES, jp.getText());
87 assertToken(JsonToken.VALUE_STRING, jp.nextToken());
88 assertEquals("d", jp.getText());
89 assertToken(JsonToken.END_OBJECT, jp.nextToken());
104 gen.writeEndArray();
105 }
106
107 private void _verifySimple(JsonParser p) throws Exception
108 {
109 assertToken(JsonToken.START_ARRAY, p.nextToken());
110
111 assertToken(JsonToken.START_OBJECT, p.nextToken());
112 assertToken(JsonToken.FIELD_NAME, p.nextToken());
113 assertEquals(NAME_WITH_QUOTES, p.getText());
114 assertToken(JsonToken.VALUE_STRING, p.nextToken());
115 assertEquals("a", p.getText());
116 assertToken(JsonToken.FIELD_NAME, p.nextToken());
117 assertEquals(NAME_WITH_LATIN1, p.getText());
118 assertToken(JsonToken.VALUE_STRING, p.nextToken());
119 assertEquals("b", p.getText());
120 assertToken(JsonToken.END_OBJECT, p.nextToken());
121
122 assertToken(JsonToken.START_OBJECT, p.nextToken());
123 assertToken(JsonToken.FIELD_NAME, p.nextToken());
124 assertEquals(NAME_WITH_LATIN1, p.getText());
125 assertToken(JsonToken.VALUE_STRING, p.nextToken());
126 assertEquals("c", p.getText());
127 assertToken(JsonToken.FIELD_NAME, p.nextToken());
128 assertEquals(NAME_WITH_QUOTES, p.getText());
129 assertToken(JsonToken.VALUE_STRING, p.nextToken());
130 assertEquals("d", p.getText());
131 assertToken(JsonToken.END_OBJECT, p.nextToken());
90132
91 assertToken(JsonToken.END_ARRAY, jp.nextToken());
92 assertNull(jp.nextToken());
133 assertToken(JsonToken.END_ARRAY, p.nextToken());
134 assertNull(p.nextToken());
135 }
136
137 private void _verifySimpleValues(JsonParser p) throws Exception
138 {
139 assertToken(JsonToken.START_ARRAY, p.nextToken());
140
141 assertToken(JsonToken.START_OBJECT, p.nextToken());
142 assertToken(JsonToken.FIELD_NAME, p.nextToken());
143 assertEquals(NAME_WITH_QUOTES, p.getText());
144 assertToken(JsonToken.VALUE_STRING, p.nextToken());
145 assertEquals(VALUE_WITH_QUOTES, p.getText());
146 assertToken(JsonToken.FIELD_NAME, p.nextToken());
147 assertEquals(NAME_WITH_LATIN1, p.getText());
148 assertToken(JsonToken.VALUE_STRING, p.nextToken());
149 assertEquals(VALUE2, p.getText());
150 assertToken(JsonToken.END_OBJECT, p.nextToken());
151
152 assertToken(JsonToken.START_OBJECT, p.nextToken());
153 assertToken(JsonToken.FIELD_NAME, p.nextToken());
154 assertEquals(NAME_WITH_LATIN1, p.getText());
155 assertToken(JsonToken.VALUE_STRING, p.nextToken());
156 assertEquals(VALUE_WITH_QUOTES, p.getText());
157 assertToken(JsonToken.FIELD_NAME, p.nextToken());
158 assertEquals(NAME_WITH_QUOTES, p.getText());
159 assertToken(JsonToken.VALUE_STRING, p.nextToken());
160 assertEquals(VALUE2, p.getText());
161 assertToken(JsonToken.END_OBJECT, p.nextToken());
162
163 assertToken(JsonToken.END_ARRAY, p.nextToken());
164 assertNull(p.nextToken());
165 }
166
167 private static String _generateLongName(int minLen)
168 {
169 StringBuilder sb = new StringBuilder();
170 Random rnd = new Random(123);
171 while (sb.length() < minLen) {
172 int ch = rnd.nextInt(96);
173 if (ch < 32) { // ascii (single byte)
174 sb.append((char) (48 + ch));
175 } else if (ch < 64) { // 2 byte
176 sb.append((char) (128 + ch));
177 } else { // 3 byte
178 sb.append((char) (4000 + ch));
179 }
180 }
181 return sb.toString();
93182 }
94183 }
1919
2020 public void testLongErrorMessageReader() throws Exception
2121 {
22 _testLongErrorMessage(MODE_READER);
22 _testLongErrorMessage(MODE_READER);
2323 }
2424
2525 private void _testLongErrorMessage(int mode) throws Exception
3535 fail("Expected an exception for unrecognized token");
3636 } catch (JsonParseException jpe) {
3737 String msg = jpe.getMessage();
38 final String expectedPrefix = "Unrecognized token '";
39 final String expectedSuffix = "...': was expecting ('true', 'false' or 'null')";
40 assertTrue(msg.startsWith(expectedPrefix));
38 final String expectedPrefix = "Unrecognized token '";
39 final String expectedSuffix = "...': was expecting";
40 verifyException(jpe, expectedPrefix);
41 verifyException(jpe, expectedSuffix);
4142 assertTrue(msg.contains(expectedSuffix));
4243 int tokenLen = msg.indexOf (expectedSuffix) - expectedPrefix.length();
4344 assertEquals(EXPECTED_MAX_TOKEN_LEN, tokenLen);
6465 } catch (JsonParseException jpe) {
6566 String msg = jpe.getMessage();
6667 final String expectedPrefix = "Unrecognized token '";
67 final String expectedSuffix = "': was expecting ('true', 'false' or 'null')";
68 assertTrue(msg.startsWith(expectedPrefix));
69 assertTrue(msg.contains(expectedSuffix));
70 int tokenLen = msg.indexOf (expectedSuffix) - expectedPrefix.length();
68 final String expectedSuffix = "': was expecting";
69 verifyException(jpe, expectedPrefix);
70 verifyException(jpe, expectedSuffix);
71 int tokenLen = msg.indexOf(expectedSuffix) - expectedPrefix.length();
7172 assertEquals(DOC.length(), tokenLen);
7273 }
7374 jp.close();
00 package com.fasterxml.jackson.core.json;
11
2 import com.fasterxml.jackson.core.BaseTest;
3 import com.fasterxml.jackson.core.JsonFactory;
4 import com.fasterxml.jackson.core.JsonGenerator;
5 import com.fasterxml.jackson.core.JsonParser;
6 import com.fasterxml.jackson.core.JsonToken;
2 import com.fasterxml.jackson.core.*;
73 import com.fasterxml.jackson.core.filter.FilteringGeneratorDelegate;
84 import com.fasterxml.jackson.core.filter.JsonPointerBasedFilter;
95 import com.fasterxml.jackson.core.io.IOContext;
1915 {
2016 ByteArrayOutputStream bytes = new ByteArrayOutputStream();
2117 IOContext ioc = new IOContext(new BufferRecycler(), bytes, true);
22 JsonGenerator gen = new UTF8JsonGenerator(ioc, 0, null, bytes);
18 JsonGenerator gen = new UTF8JsonGenerator(ioc, 0, null, bytes, '"');
2319 String str = "Natuurlijk is alles gelukt en weer een tevreden klant\uD83D\uDE04";
2420 int length = 4000 - 38;
2521
33
44 import com.fasterxml.jackson.core.*;
55 import com.fasterxml.jackson.core.async.AsyncTestBase;
6 import com.fasterxml.jackson.core.json.JsonReadFeature;
67 import com.fasterxml.jackson.core.testsupport.AsyncReaderWrapper;
78
89 /**
5556
5657 public void testYAMLCommentsEnabled() throws Exception
5758 {
58 JsonFactory f = new JsonFactory();
59 f.enable(JsonParser.Feature.ALLOW_YAML_COMMENTS);
60
59 final JsonFactory f = JsonFactory.builder()
60 .enable(JsonReadFeature.ALLOW_YAML_COMMENTS)
61 .build();
6162 _testYAMLComments(f, 99);
6263 _testYAMLComments(f, 3);
6364 _testYAMLComments(f, 1);
7273 }
7374
7475 public void testCCommentsEnabled() throws Exception {
75 JsonFactory f = new JsonFactory();
76 f.enable(JsonParser.Feature.ALLOW_COMMENTS);
76 final JsonFactory f = JsonFactory.builder()
77 .enable(JsonReadFeature.ALLOW_JAVA_COMMENTS)
78 .build();
7779 final String COMMENT = "/* foo */\n";
7880 _testCommentsBeforePropValue(f, COMMENT, 99);
7981 _testCommentsBeforePropValue(f, COMMENT, 3);
8183 }
8284
8385 public void testCppCommentsEnabled() throws Exception {
84 JsonFactory f = new JsonFactory();
85 f.enable(JsonParser.Feature.ALLOW_COMMENTS);
86 final JsonFactory f = JsonFactory.builder()
87 .enable(JsonReadFeature.ALLOW_JAVA_COMMENTS)
88 .build();
8689 final String COMMENT = "// foo\n";
8790 _testCommentsBeforePropValue(f, COMMENT, 99);
8891 _testCommentsBeforePropValue(f, COMMENT, 3);
240243 int bytesPerRead)
241244 throws IOException
242245 {
243 JsonFactory f = new JsonFactory();
244 f.configure(JsonParser.Feature.ALLOW_COMMENTS, enabled);
246 final JsonFactory f = JsonFactory.builder()
247 .configure(JsonReadFeature.ALLOW_JAVA_COMMENTS, enabled)
248 .build();
245249 return asyncForBytes(f, bytesPerRead, _jsonDoc(doc), 0);
246250 }
247251
33
44 import com.fasterxml.jackson.core.*;
55 import com.fasterxml.jackson.core.async.AsyncTestBase;
6 import com.fasterxml.jackson.core.json.JsonReadFeature;
67 import com.fasterxml.jackson.core.testsupport.AsyncReaderWrapper;
78
89 public class AsyncFieldNamesTest extends AsyncTestBase
910 {
1011 private final JsonFactory JSON_F = new JsonFactory();
1112
12 private final JsonFactory JSON_APOS_F = new JsonFactory();
13 {
14 JSON_APOS_F.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
15 }
13 private final JsonFactory JSON_APOS_F = JsonFactory.builder()
14 .enable(JsonReadFeature.ALLOW_SINGLE_QUOTES)
15 .build();
1616
1717 // Mainly to test "fast" parse for shortish names
1818 public void testSimpleFieldNames() throws IOException
33 import java.util.*;
44
55 import com.fasterxml.jackson.core.*;
6 import com.fasterxml.jackson.core.JsonParser.Feature;
76 import com.fasterxml.jackson.core.async.AsyncTestBase;
7 import com.fasterxml.jackson.core.json.JsonReadFeature;
88 import com.fasterxml.jackson.core.testsupport.AsyncReaderWrapper;
99
1010 import org.junit.Test;
1515 public class AsyncMissingValuesInArrayTest extends AsyncTestBase
1616 {
1717 private final JsonFactory factory;
18 private final HashSet<JsonParser.Feature> features;
19
20 public AsyncMissingValuesInArrayTest(Collection<JsonParser.Feature> features) {
21 this.factory = new JsonFactory();
22 this.features = new HashSet<JsonParser.Feature>(features);
23
24 for (JsonParser.Feature feature : features) {
25 factory.enable(feature);
18 private final HashSet<JsonReadFeature> features;
19
20 public AsyncMissingValuesInArrayTest(Collection<JsonReadFeature> features) {
21 this.features = new HashSet<JsonReadFeature>(features);
22 JsonFactoryBuilder b = (JsonFactoryBuilder) JsonFactory.builder();
23 for (JsonReadFeature feature : features) {
24 b = b.enable(feature);
2625 }
26 factory = b.build();
2727 }
2828
2929 @Parameterized.Parameters(name = "Features {0}")
30 public static Collection<EnumSet<JsonParser.Feature>> getTestCases()
30 public static Collection<EnumSet<JsonReadFeature>> getTestCases()
3131 {
32 List<EnumSet<JsonParser.Feature>> cases = new ArrayList<EnumSet<JsonParser.Feature>>();
33 cases.add(EnumSet.noneOf(JsonParser.Feature.class));
34 cases.add(EnumSet.of(Feature.ALLOW_MISSING_VALUES));
35 cases.add(EnumSet.of(Feature.ALLOW_TRAILING_COMMA));
36 cases.add(EnumSet.of(Feature.ALLOW_MISSING_VALUES, Feature.ALLOW_TRAILING_COMMA));
32 List<EnumSet<JsonReadFeature>> cases = new ArrayList<EnumSet<JsonReadFeature>>();
33 cases.add(EnumSet.noneOf(JsonReadFeature.class));
34 cases.add(EnumSet.of(JsonReadFeature.ALLOW_MISSING_VALUES));
35 cases.add(EnumSet.of(JsonReadFeature.ALLOW_TRAILING_COMMA));
36 cases.add(EnumSet.of(JsonReadFeature.ALLOW_MISSING_VALUES, JsonReadFeature.ALLOW_TRAILING_COMMA));
3737 return cases;
3838 }
3939
6969 assertToken(JsonToken.VALUE_STRING, p.nextToken());
7070 assertEquals("a", p.currentText());
7171
72 if (!features.contains(Feature.ALLOW_MISSING_VALUES)) {
72 if (!features.contains(JsonReadFeature.ALLOW_MISSING_VALUES)) {
7373 assertUnexpected(p, ',');
7474 return;
7575 }
9191
9292 assertEquals(JsonToken.START_ARRAY, p.nextToken());
9393
94 if (!features.contains(Feature.ALLOW_MISSING_VALUES)) {
94 if (!features.contains(JsonReadFeature.ALLOW_MISSING_VALUES)) {
9595 assertUnexpected(p, ',');
9696 return;
9797 }
124124 assertEquals("b", p.currentText());
125125
126126 // ALLOW_TRAILING_COMMA takes priority over ALLOW_MISSING_VALUES
127 if (features.contains(Feature.ALLOW_TRAILING_COMMA)) {
128 assertToken(JsonToken.END_ARRAY, p.nextToken());
129 assertEnd(p);
130 } else if (features.contains(Feature.ALLOW_MISSING_VALUES)) {
127 if (features.contains(JsonReadFeature.ALLOW_TRAILING_COMMA)) {
128 assertToken(JsonToken.END_ARRAY, p.nextToken());
129 assertEnd(p);
130 } else if (features.contains(JsonReadFeature.ALLOW_MISSING_VALUES)) {
131131 assertToken(JsonToken.VALUE_NULL, p.nextToken());
132132 assertToken(JsonToken.END_ARRAY, p.nextToken());
133133 assertEnd(p);
152152 assertEquals("b", p.currentText());
153153
154154 // ALLOW_TRAILING_COMMA takes priority over ALLOW_MISSING_VALUES
155 if (features.contains(Feature.ALLOW_MISSING_VALUES) &&
156 features.contains(Feature.ALLOW_TRAILING_COMMA)) {
157 assertToken(JsonToken.VALUE_NULL, p.nextToken());
158 assertToken(JsonToken.END_ARRAY, p.nextToken());
159 assertEnd(p);
160 } else if (features.contains(Feature.ALLOW_MISSING_VALUES)) {
155 if (features.contains(JsonReadFeature.ALLOW_MISSING_VALUES) &&
156 features.contains(JsonReadFeature.ALLOW_TRAILING_COMMA)) {
157 assertToken(JsonToken.VALUE_NULL, p.nextToken());
158 assertToken(JsonToken.END_ARRAY, p.nextToken());
159 assertEnd(p);
160 } else if (features.contains(JsonReadFeature.ALLOW_MISSING_VALUES)) {
161161 assertToken(JsonToken.VALUE_NULL, p.nextToken());
162162 assertToken(JsonToken.VALUE_NULL, p.nextToken());
163163 assertToken(JsonToken.END_ARRAY, p.nextToken());
183183 assertEquals("b", p.currentText());
184184
185185 // ALLOW_TRAILING_COMMA takes priority over ALLOW_MISSING_VALUES
186 if (features.contains(Feature.ALLOW_MISSING_VALUES) &&
187 features.contains(Feature.ALLOW_TRAILING_COMMA)) {
188 assertToken(JsonToken.VALUE_NULL, p.nextToken());
189 assertToken(JsonToken.VALUE_NULL, p.nextToken());
190 assertToken(JsonToken.END_ARRAY, p.nextToken());
191 assertEnd(p);
192 } else if (features.contains(Feature.ALLOW_MISSING_VALUES)) {
186 if (features.contains(JsonReadFeature.ALLOW_MISSING_VALUES) &&
187 features.contains(JsonReadFeature.ALLOW_TRAILING_COMMA)) {
188 assertToken(JsonToken.VALUE_NULL, p.nextToken());
189 assertToken(JsonToken.VALUE_NULL, p.nextToken());
190 assertToken(JsonToken.END_ARRAY, p.nextToken());
191 assertEnd(p);
192 } else if (features.contains(JsonReadFeature.ALLOW_MISSING_VALUES)) {
193193 assertToken(JsonToken.VALUE_NULL, p.nextToken());
194194 assertToken(JsonToken.VALUE_NULL, p.nextToken());
195195 assertToken(JsonToken.VALUE_NULL, p.nextToken());
66 import org.junit.runner.RunWith;
77 import org.junit.runners.Parameterized;
88
9 import com.fasterxml.jackson.core.JsonFactory;
10 import com.fasterxml.jackson.core.JsonParseException;
11 import com.fasterxml.jackson.core.JsonParser;
12 import com.fasterxml.jackson.core.JsonToken;
13 import com.fasterxml.jackson.core.JsonParser.Feature;
9 import com.fasterxml.jackson.core.*;
1410 import com.fasterxml.jackson.core.async.AsyncTestBase;
11 import com.fasterxml.jackson.core.json.JsonReadFeature;
1512 import com.fasterxml.jackson.core.testsupport.AsyncReaderWrapper;
1613
1714 @RunWith(Parameterized.class)
1815 public class AsyncMissingValuesInObjectTest extends AsyncTestBase
1916 {
2017 private JsonFactory factory;
21 private HashSet<JsonParser.Feature> features;
18 private HashSet<JsonReadFeature> features;
2219
23 public AsyncMissingValuesInObjectTest(Collection<JsonParser.Feature> features) {
24 this.factory = new JsonFactory();
25 this.features = new HashSet<JsonParser.Feature>(features);
26
27 for (JsonParser.Feature feature : features) {
28 factory.enable(feature);
20 public AsyncMissingValuesInObjectTest(Collection<JsonReadFeature> features) {
21 this.features = new HashSet<JsonReadFeature>(features);
22 JsonFactoryBuilder b = (JsonFactoryBuilder) JsonFactory.builder();
23 for (JsonReadFeature feature : features) {
24 b = b.enable(feature);
2925 }
26 factory = b.build();
3027 }
3128
3229 @Parameterized.Parameters(name = "Features {0}")
33 public static Collection<EnumSet<JsonParser.Feature>> getTestCases()
30 public static Collection<EnumSet<JsonReadFeature>> getTestCases()
3431 {
35 List<EnumSet<JsonParser.Feature>> cases = new ArrayList<EnumSet<JsonParser.Feature>>();
36 cases.add(EnumSet.noneOf(JsonParser.Feature.class));
37 cases.add(EnumSet.of(Feature.ALLOW_MISSING_VALUES));
38 cases.add(EnumSet.of(Feature.ALLOW_TRAILING_COMMA));
39 cases.add(EnumSet.of(Feature.ALLOW_MISSING_VALUES, Feature.ALLOW_TRAILING_COMMA));
32 List<EnumSet<JsonReadFeature>> cases = new ArrayList<EnumSet<JsonReadFeature>>();
33 cases.add(EnumSet.noneOf(JsonReadFeature.class));
34 cases.add(EnumSet.of(JsonReadFeature.ALLOW_MISSING_VALUES));
35 cases.add(EnumSet.of(JsonReadFeature.ALLOW_TRAILING_COMMA));
36 cases.add(EnumSet.of(JsonReadFeature.ALLOW_MISSING_VALUES, JsonReadFeature.ALLOW_TRAILING_COMMA));
4037 return cases;
4138 }
4239
105102 assertEquals("b", p.currentText());
106103 assertToken(JsonToken.VALUE_FALSE, p.nextToken());
107104
108 if (features.contains(Feature.ALLOW_TRAILING_COMMA)) {
105 if (features.contains(JsonReadFeature.ALLOW_TRAILING_COMMA)) {
109106 assertToken(JsonToken.END_OBJECT, p.nextToken());
110107 assertEnd(p);
111108 } else {
33
44 import com.fasterxml.jackson.core.*;
55 import com.fasterxml.jackson.core.async.AsyncTestBase;
6 import com.fasterxml.jackson.core.json.JsonReadFeature;
67 import com.fasterxml.jackson.core.testsupport.AsyncReaderWrapper;
78
89 public class AsyncNonStdNumbersTest extends AsyncTestBase
910 {
1011 private final JsonFactory DEFAULT_F = new JsonFactory();
1112
13 @SuppressWarnings("deprecation")
14 public void testDefaultsForAsync() throws Exception {
15 assertFalse(DEFAULT_F.isEnabled(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS));
16 }
17
1218 public void testDisallowNaN() throws Exception
1319 {
1420 final String JSON = "[ NaN]";
15 assertFalse(DEFAULT_F.isEnabled(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS));
1621
1722 // without enabling, should get an exception
1823 AsyncReaderWrapper p = createParser(DEFAULT_F, JSON, 1);
3035 public void testAllowNaN() throws Exception
3136 {
3237 final String JSON = "[ NaN]";
33 JsonFactory f = new JsonFactory();
34 f.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true);
35
38 JsonFactory f = JsonFactory.builder()
39 .enable(JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS)
40 .build();
3641 _testAllowNaN(f, JSON, 99);
3742 _testAllowNaN(f, JSON, 5);
3843 _testAllowNaN(f, JSON, 3);
6166 p.close();
6267
6368 // finally, should also work with skipping
64 f.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true);
69 f = JsonFactory.builder()
70 .configure(JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS, true)
71 .build();
6572 p = createParser(f, doc, readBytes);
6673 assertToken(JsonToken.START_ARRAY, p.nextToken());
6774 assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
9097
9198 private void _testDisallowInf(JsonFactory f, String token, int readBytes) throws Exception
9299 {
93 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS));
94100 final String JSON = String.format("[%s]", token);
95101
96102 // without enabling, should get an exception
108114
109115 public void testAllowInf() throws Exception
110116 {
111 JsonFactory f = new JsonFactory();
112 f.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true);
113
117 JsonFactory f = JsonFactory.builder()
118 .enable(JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS)
119 .build();
114120 String JSON = "[ Infinity, +Infinity, -Infinity ]";
115121 _testAllowInf(f, JSON, 99);
116122 _testAllowInf(f, JSON, 5);
159165 p.close();
160166
161167 // finally, should also work with skipping
162 f.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true);
168 f = JsonFactory.builder()
169 .configure(JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS, true)
170 .build();
163171 p = createParser(f, doc, readBytes);
164172
165173 assertToken(JsonToken.START_ARRAY, p.nextToken());
33
44 import com.fasterxml.jackson.core.*;
55 import com.fasterxml.jackson.core.async.AsyncTestBase;
6 import com.fasterxml.jackson.core.json.JsonReadFeature;
67 import com.fasterxml.jackson.core.testsupport.AsyncReaderWrapper;
78
89 public class AsyncNonStdParsingTest extends AsyncTestBase
910 {
1011 public void testLargeUnquotedNames() throws Exception
1112 {
12 JsonFactory f = new JsonFactory();
13 f.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
14
13 final JsonFactory f = JsonFactory.builder()
14 .enable(JsonReadFeature.ALLOW_UNQUOTED_FIELD_NAMES)
15 .build();
1516 StringBuilder sb = new StringBuilder(5000);
1617 sb.append("[\n");
1718 final int REPS = 1050;
5859
5960 public void testSimpleUnquotedNames() throws Exception
6061 {
61 final JsonFactory f = new JsonFactory();
62 f.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
63
62 final JsonFactory f = JsonFactory.builder()
63 .enable(JsonReadFeature.ALLOW_UNQUOTED_FIELD_NAMES)
64 .build();
6465 _testSimpleUnquoted(f, 0, 99);
6566 _testSimpleUnquoted(f, 0, 5);
6667 _testSimpleUnquoted(f, 0, 3);
169170 */
170171 public void testAposQuotingEnabled() throws Exception
171172 {
172 JsonFactory f = new JsonFactory();
173 f.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
174
173 final JsonFactory f = JsonFactory.builder()
174 .enable(JsonReadFeature.ALLOW_SINGLE_QUOTES)
175 .build();
175176 _testAposQuotingEnabled(f, 0, 99);
176177 _testAposQuotingEnabled(f, 0, 5);
177178 _testAposQuotingEnabled(f, 0, 3);
267268 // test to verify that we implicitly allow escaping of apostrophe
268269 public void testSingleQuotesEscaped() throws Exception
269270 {
270 JsonFactory f = new JsonFactory();
271 f.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
272
271 final JsonFactory f = JsonFactory.builder()
272 .enable(JsonReadFeature.ALLOW_SINGLE_QUOTES)
273 .build();
273274 _testSingleQuotesEscaped(f, 0, 99);
274275 _testSingleQuotesEscaped(f, 0, 5);
275276 _testSingleQuotesEscaped(f, 0, 3);
294295
295296 public void testNonStandardNameChars() throws Exception
296297 {
297 JsonFactory f = new JsonFactory();
298 f.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
299
298 final JsonFactory f = JsonFactory.builder()
299 .enable(JsonReadFeature.ALLOW_UNQUOTED_FIELD_NAMES)
300 .build();
300301 _testNonStandardNameChars(f, 0, 99);
301302 _testNonStandardNameChars(f, 0, 6);
302303 _testNonStandardNameChars(f, 0, 3);
359360 {
360361 // first: verify that we get an exception
361362 JsonFactory f = new JsonFactory();
362 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER));
363363 final String JSON = quote("\\'");
364364 AsyncReaderWrapper p = createParser(f, JSON, offset, readSize);
365365 try {
372372 p.close();
373373 }
374374 // and then verify it's ok...
375 f.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);
376 assertTrue(f.isEnabled(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER));
375 f = f.rebuild()
376 .enable(JsonReadFeature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER)
377 .build();
377378 p = createParser(f, JSON, offset, readSize);
378379 assertToken(JsonToken.VALUE_STRING, p.nextToken());
379380 assertEquals("'", p.currentText());
44 import java.math.BigInteger;
55
66 import com.fasterxml.jackson.core.JsonFactory;
7 import com.fasterxml.jackson.core.JsonParseException;
87 import com.fasterxml.jackson.core.JsonParser.NumberType;
98 import com.fasterxml.jackson.core.async.AsyncTestBase;
9 import com.fasterxml.jackson.core.exc.InputCoercionException;
1010 import com.fasterxml.jackson.core.testsupport.AsyncReaderWrapper;
1111 import com.fasterxml.jackson.core.JsonToken;
1212
7171 try {
7272 p.getIntValue();
7373 fail("Should not pass");
74 } catch (JsonParseException e) {
75 verifyException(e, "out of range of int");
74 } catch (InputCoercionException e) {
75 verifyException(e, "out of range of int");
76 assertEquals(JsonToken.VALUE_NUMBER_INT, e.getInputType());
77 assertEquals(Integer.TYPE, e.getTargetType());
7678 }
7779 long small = -1L + Integer.MIN_VALUE;
7880 p = createParser(String.valueOf(small));
8284 try {
8385 p.getIntValue();
8486 fail("Should not pass");
85 } catch (JsonParseException e) {
86 verifyException(e, "out of range of int");
87 } catch (InputCoercionException e) {
88 verifyException(e, "out of range of int");
89 assertEquals(JsonToken.VALUE_NUMBER_INT, e.getInputType());
90 assertEquals(Integer.TYPE, e.getTargetType());
8791 }
8892
8993 // double -> error
9397 try {
9498 p.getIntValue();
9599 fail("Should not pass");
96 } catch (JsonParseException e) {
97 verifyException(e, "out of range of int");
100 } catch (InputCoercionException e) {
101 verifyException(e, "out of range of int");
102 assertEquals(JsonToken.VALUE_NUMBER_INT, e.getInputType());
103 assertEquals(Integer.TYPE, e.getTargetType());
98104 }
99105 p = createParser(String.valueOf(small)+".0");
100106 assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
102108 try {
103109 p.getIntValue();
104110 fail("Should not pass");
105 } catch (JsonParseException e) {
106 verifyException(e, "out of range of int");
111 } catch (InputCoercionException e) {
112 verifyException(e, "out of range of int");
113 assertEquals(JsonToken.VALUE_NUMBER_INT, e.getInputType());
114 assertEquals(Integer.TYPE, e.getTargetType());
107115 }
108116
109117 // BigInteger -> error
113121 try {
114122 p.getIntValue();
115123 fail("Should not pass");
116 } catch (JsonParseException e) {
117 verifyException(e, "out of range of int");
124 } catch (InputCoercionException e) {
125 verifyException(e, "out of range of int");
126 assertEquals(JsonToken.VALUE_NUMBER_INT, e.getInputType());
127 assertEquals(Integer.TYPE, e.getTargetType());
118128 }
119129 p = createParser(String.valueOf(small));
120130 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
122132 try {
123133 p.getIntValue();
124134 fail("Should not pass");
125 } catch (JsonParseException e) {
126 verifyException(e, "out of range of int");
135 } catch (InputCoercionException e) {
136 verifyException(e, "out of range of int");
137 assertEquals(JsonToken.VALUE_NUMBER_INT, e.getInputType());
138 assertEquals(Integer.TYPE, e.getTargetType());
127139 }
128140 }
129141
175187 try {
176188 p.getLongValue();
177189 fail("Should not pass");
178 } catch (JsonParseException e) {
190 } catch (InputCoercionException e) {
179191 verifyException(e, "out of range of long");
192 assertEquals(JsonToken.VALUE_NUMBER_INT, e.getInputType());
193 assertEquals(Long.TYPE, e.getTargetType());
180194 }
181195 BigInteger small = BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.TEN);
182196 p = createParser(String.valueOf(small));
185199 try {
186200 p.getLongValue();
187201 fail("Should not pass");
188 } catch (JsonParseException e) {
202 } catch (InputCoercionException e) {
189203 verifyException(e, "out of range of long");
204 assertEquals(JsonToken.VALUE_NUMBER_INT, e.getInputType());
205 assertEquals(Long.TYPE, e.getTargetType());
190206 }
191207 }
192208
33
44 import com.fasterxml.jackson.core.*;
55 import com.fasterxml.jackson.core.async.AsyncTestBase;
6 import com.fasterxml.jackson.core.json.JsonReadFeature;
67 import com.fasterxml.jackson.core.testsupport.AsyncReaderWrapper;
78
89 public class AsyncNumberLeadingZeroesTest extends AsyncTestBase
910 {
11 @SuppressWarnings("deprecation")
12 public void testDefaultsForAsync() throws Exception {
13 JsonFactory f = new JsonFactory();
14 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS));
15 }
16
1017 public void testLeadingZeroesInt() throws Exception
1118 {
1219 _testLeadingZeroesInt("00003", 3);
3340 public void _testLeadingZeroesInt(String valueStr, int value) throws Exception
3441 {
3542 // first: verify that we get an exception
43
3644 JsonFactory f = new JsonFactory();
37 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS));
3845 String JSON = valueStr;
3946 AsyncReaderWrapper p = createParser(f, JSON);
4047 try {
4855 }
4956
5057 // and then verify it's ok when enabled
51 f.configure(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS, true);
52 assertTrue(f.isEnabled(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS));
58 f = JsonFactory.builder()
59 .enable(JsonReadFeature.ALLOW_LEADING_ZEROS_FOR_NUMBERS)
60 .build();
5361 p = createParser(f, JSON);
5462 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
5563 assertEquals(value, p.getIntValue());
7280 {
7381 // first: verify that we get an exception
7482 JsonFactory f = new JsonFactory();
75 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS));
7683 String JSON = valueStr;
7784 AsyncReaderWrapper p = createParser(f, JSON);
7885 try {
8693 }
8794
8895 // and then verify it's ok when enabled
89 f.configure(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS, true);
90 assertTrue(f.isEnabled(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS));
96 f = JsonFactory.builder()
97 .enable(JsonReadFeature.ALLOW_LEADING_ZEROS_FOR_NUMBERS)
98 .build();
9199 p = createParser(f, JSON);
92100 assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
93101 assertEquals(String.valueOf(value), p.currentText());
0 package com.fasterxml.jackson.core.json.async;
1
2 import com.fasterxml.jackson.core.*;
3 import com.fasterxml.jackson.core.async.AsyncTestBase;
4 import com.fasterxml.jackson.core.testsupport.AsyncReaderWrapper;
5
6 public class AsyncPointerFromContext563Test extends AsyncTestBase
7 {
8 private final JsonFactory JSON_F = new JsonFactory();
9
10 // [core#563]
11 public void testPointerWithAsyncParser() throws Exception
12 {
13 final String SIMPLE = aposToQuotes("{'a':123,'array':[1,2,[3],5,{'obInArray':4}],"
14 +"'ob':{'first':[false,true],'second':{'sub':37}},'b':true}");
15 byte[] SIMPLE_BYTES = SIMPLE.getBytes("UTF-8");
16
17 _testPointerWithAsyncParser(SIMPLE_BYTES, 0, 1000);
18 _testPointerWithAsyncParser(SIMPLE_BYTES, 0, 7);
19 _testPointerWithAsyncParser(SIMPLE_BYTES, 0, 3);
20 _testPointerWithAsyncParser(SIMPLE_BYTES, 0, 2);
21 _testPointerWithAsyncParser(SIMPLE_BYTES, 0, 1);
22
23 _testPointerWithAsyncParser(SIMPLE_BYTES, 20, 5);
24 _testPointerWithAsyncParser(SIMPLE_BYTES, 14, 1);
25 }
26
27 public void _testPointerWithAsyncParser(byte[] doc, int offset, int readSize) throws Exception
28 {
29 AsyncReaderWrapper p = asyncForBytes(JSON_F, readSize, doc, offset);
30
31 // by default should just get "empty"
32 assertSame(JsonPointer.empty(), p.getParsingContext().pathAsPointer());
33
34 // let's just traverse, then:
35 assertToken(JsonToken.START_OBJECT, p.nextToken());
36 assertSame(JsonPointer.empty(), p.getParsingContext().pathAsPointer());
37
38 assertEquals("", p.getParsingContext().pathAsPointer().toString());
39
40 assertToken(JsonToken.FIELD_NAME, p.nextToken()); // a
41 assertEquals("/a", p.getParsingContext().pathAsPointer().toString());
42
43 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
44 assertEquals("/a", p.getParsingContext().pathAsPointer().toString());
45
46 assertToken(JsonToken.FIELD_NAME, p.nextToken()); // array
47 assertEquals("/array", p.getParsingContext().pathAsPointer().toString());
48 assertToken(JsonToken.START_ARRAY, p.nextToken());
49 assertEquals("/array", p.getParsingContext().pathAsPointer().toString());
50 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); // 1
51 assertEquals("/array/0", p.getParsingContext().pathAsPointer().toString());
52 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); // 2
53 assertEquals("/array/1", p.getParsingContext().pathAsPointer().toString());
54 assertToken(JsonToken.START_ARRAY, p.nextToken());
55 assertEquals("/array/2", p.getParsingContext().pathAsPointer().toString());
56 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); // 3
57 assertEquals("/array/2/0", p.getParsingContext().pathAsPointer().toString());
58 assertToken(JsonToken.END_ARRAY, p.nextToken());
59 assertEquals("/array/2", p.getParsingContext().pathAsPointer().toString());
60 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); // 5
61 assertEquals("/array/3", p.getParsingContext().pathAsPointer().toString());
62 assertToken(JsonToken.START_OBJECT, p.nextToken());
63 assertEquals("/array/4", p.getParsingContext().pathAsPointer().toString());
64 assertToken(JsonToken.FIELD_NAME, p.nextToken()); // obInArray
65 assertEquals("/array/4/obInArray", p.getParsingContext().pathAsPointer().toString());
66 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); // 4
67 assertEquals("/array/4/obInArray", p.getParsingContext().pathAsPointer().toString());
68 assertToken(JsonToken.END_OBJECT, p.nextToken());
69 assertEquals("/array/4", p.getParsingContext().pathAsPointer().toString());
70 assertToken(JsonToken.END_ARRAY, p.nextToken()); // /array
71 assertEquals("/array", p.getParsingContext().pathAsPointer().toString());
72
73 assertToken(JsonToken.FIELD_NAME, p.nextToken()); // ob
74 assertEquals("/ob", p.getParsingContext().pathAsPointer().toString());
75 assertToken(JsonToken.START_OBJECT, p.nextToken());
76 assertEquals("/ob", p.getParsingContext().pathAsPointer().toString());
77 assertToken(JsonToken.FIELD_NAME, p.nextToken()); // first
78 assertEquals("/ob/first", p.getParsingContext().pathAsPointer().toString());
79 assertToken(JsonToken.START_ARRAY, p.nextToken());
80 assertEquals("/ob/first", p.getParsingContext().pathAsPointer().toString());
81 assertToken(JsonToken.VALUE_FALSE, p.nextToken());
82 assertEquals("/ob/first/0", p.getParsingContext().pathAsPointer().toString());
83 assertToken(JsonToken.VALUE_TRUE, p.nextToken());
84 assertEquals("/ob/first/1", p.getParsingContext().pathAsPointer().toString());
85 assertToken(JsonToken.END_ARRAY, p.nextToken());
86 assertEquals("/ob/first", p.getParsingContext().pathAsPointer().toString());
87 assertToken(JsonToken.FIELD_NAME, p.nextToken()); // second
88 assertEquals("/ob/second", p.getParsingContext().pathAsPointer().toString());
89 assertToken(JsonToken.START_OBJECT, p.nextToken());
90 assertEquals("/ob/second", p.getParsingContext().pathAsPointer().toString());
91 assertToken(JsonToken.FIELD_NAME, p.nextToken()); // sub
92 assertEquals("/ob/second/sub", p.getParsingContext().pathAsPointer().toString());
93 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); // 37
94 assertEquals("/ob/second/sub", p.getParsingContext().pathAsPointer().toString());
95 assertToken(JsonToken.END_OBJECT, p.nextToken());
96 assertEquals("/ob/second", p.getParsingContext().pathAsPointer().toString());
97 assertToken(JsonToken.END_OBJECT, p.nextToken()); // /ob
98 assertEquals("/ob", p.getParsingContext().pathAsPointer().toString());
99
100 assertToken(JsonToken.FIELD_NAME, p.nextToken()); // b
101 assertEquals("/b", p.getParsingContext().pathAsPointer().toString());
102 assertToken(JsonToken.VALUE_TRUE, p.nextToken());
103 assertEquals("/b", p.getParsingContext().pathAsPointer().toString());
104
105 assertToken(JsonToken.END_OBJECT, p.nextToken());
106 assertSame(JsonPointer.empty(), p.getParsingContext().pathAsPointer());
107
108 // note: wrapper maps to `null`, plain async-parser would give NOT_AVAILABLE
109 assertNull(p.nextToken());
110 p.close();
111 }
112 }
5151 public void testSkipChildrenFailOnSplit() throws IOException
5252 {
5353 NonBlockingJsonParser nbParser = (NonBlockingJsonParser) JSON_F.createNonBlockingByteArrayParser();
54 @SuppressWarnings("resource")
5455 FilteringParserDelegate filteredParser = new FilteringParserDelegate(nbParser,
5556 TOKEN_FILTER, true, true);
5657 nbParser.feedInput(INPUT_BYTES, 0, 5);
00 package com.fasterxml.jackson.core.main;
11
22 import com.fasterxml.jackson.core.*;
3 import com.fasterxml.jackson.core.json.JsonReadFeature;
34
45 /**
56 * Set of additional unit for verifying array parsing, specifically
100101 */
101102 public void testNotMissingValueByEnablingFeature() throws Exception
102103 {
103 _testNotMissingValueByEnablingFeature(true);
104 _testNotMissingValueByEnablingFeature(false);
104 _testNotMissingValueByEnablingFeature(true);
105 _testNotMissingValueByEnablingFeature(false);
105106 }
106107
107108 private void _testMissingValueByEnablingFeature(boolean useStream) throws Exception {
108109 String DOC = "[ \"a\",,,,\"abc\", ] ";
109110
110 JsonFactory f = new JsonFactory();
111 f.configure(JsonParser.Feature.ALLOW_MISSING_VALUES, true);
112
111 JsonFactory f = JsonFactory.builder()
112 .enable(JsonReadFeature.ALLOW_MISSING_VALUES)
113 .build();
113114 JsonParser jp = useStream ? createParserUsingStream(f, DOC, "UTF-8")
114115 : createParserUsingReader(f, DOC);
115116
163164 }
164165
165166 private void _testNotMissingValueByEnablingFeature(boolean useStream) throws Exception {
166 final String DOC = "[ \"a\",\"abc\"] ";
167 final String DOC = "[ \"a\",\"abc\"] ";
167168
168 JsonFactory f = new JsonFactory();
169 f.configure(JsonParser.Feature.ALLOW_MISSING_VALUES, true);
170
169 JsonFactory f = JsonFactory.builder()
170 .enable(JsonReadFeature.ALLOW_MISSING_VALUES)
171 .build();
171172 JsonParser jp = useStream ? createParserUsingStream(f, DOC, "UTF-8")
172173 : createParserUsingReader(f, DOC);
173174
8686 {
8787 JsonFactory f = new JsonFactory();
8888 // let's verify default setting, first:
89 assertTrue(f.isEnabled(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT));
89 assertTrue(f.isEnabled(StreamWriteFeature.AUTO_CLOSE_CONTENT));
9090 StringWriter sw = new StringWriter();
9191
9292 // First, test arrays:
106106 public void testNoAutoCloseArraysAndObjects()
107107 throws Exception
108108 {
109 JsonFactory f = new JsonFactory();
110 f.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT);
109 JsonFactory f = JsonFactory.builder()
110 .disable(StreamWriteFeature.AUTO_CLOSE_CONTENT)
111 .build();
111112 StringWriter sw = new StringWriter();
112113 JsonGenerator jg = f.createGenerator(sw);
113114 jg.writeStartArray();
127128 public void testAutoFlushOrNot() throws Exception
128129 {
129130 JsonFactory f = new JsonFactory();
130 assertTrue(f.isEnabled(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM));
131 assertTrue(f.isEnabled(StreamWriteFeature.FLUSH_PASSED_TO_STREAM));
131132 StringWriterForTesting sw = new StringWriterForTesting();
132133 JsonGenerator jg = f.createGenerator(sw);
133134 jg.writeStartArray();
149150 jg.close();
150151
151152 // then disable and we should not see flushing again...
152 f.disable(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM);
153 f = JsonFactory.builder()
154 .disable(StreamWriteFeature.FLUSH_PASSED_TO_STREAM)
155 .build();
153156 // first with a Writer
154157 sw = new StringWriterForTesting();
155158 jg = f.createGenerator(sw);
2323 {
2424 final String DOC = "[ 1 ]";
2525
26 JsonFactory f = new JsonFactory();
27
2826 // Check the default settings
29 assertTrue(f.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE));
27 assertTrue(sharedStreamFactory().isEnabled(StreamReadFeature.AUTO_CLOSE_SOURCE));
3028 // then change
31 f.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE);
32 assertFalse(f.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE));
29 JsonFactory f = JsonFactory.builder()
30 .disable(StreamReadFeature.AUTO_CLOSE_SOURCE)
31 .build();
32 assertFalse(f.isEnabled(StreamReadFeature.AUTO_CLOSE_SOURCE));
33 {
34 assertFalse(f.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE));
35 }
3336 @SuppressWarnings("resource")
3437 MyReader input = new MyReader(DOC);
3538 JsonParser jp = f.createParser(input);
5255 {
5356 final String DOC = "[ 1 ]";
5457
55 JsonFactory f = new JsonFactory();
56 f.enable(JsonParser.Feature.AUTO_CLOSE_SOURCE);
57 assertTrue(f.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE));
58 JsonFactory f = JsonFactory.builder()
59 .enable(StreamReadFeature.AUTO_CLOSE_SOURCE)
60 .build();
5861 MyReader input = new MyReader(DOC);
5962 JsonParser jp = f.createParser(input);
6063 assertFalse(input.isClosed());
7881 public void testNoAutoCloseInputStream() throws Exception
7982 {
8083 final String DOC = "[ 1 ]";
81 JsonFactory f = new JsonFactory();
82
83 f.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE);
84 JsonFactory f = JsonFactory.builder()
85 .disable(StreamReadFeature.AUTO_CLOSE_SOURCE)
86 .build();
8487 MyStream input = new MyStream(DOC.getBytes("UTF-8"));
8588 JsonParser jp = f.createParser(input);
8689
22 import java.io.*;
33
44 import com.fasterxml.jackson.core.*;
5 import com.fasterxml.jackson.core.json.JsonReadFeature;
56
67 /**
78 * Unit tests for verifying that additional <code>JsonParser.Feature</code>
1314 public void testDefaultSettings() throws Exception
1415 {
1516 JsonFactory f = new JsonFactory();
16 assertTrue(f.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE));
17 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_COMMENTS));
18 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES));
19 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_SINGLE_QUOTES));
20 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS));
17 assertTrue(f.isEnabled(StreamReadFeature.AUTO_CLOSE_SOURCE));
2118
2219 JsonParser p = f.createParser(new StringReader("{}"));
2320 _testDefaultSettings(p);
2724 p.close();
2825 }
2926
27 @SuppressWarnings("deprecation")
28 public void testDeprecatedDefaultSettings() throws Exception
29 {
30 JsonFactory f = sharedStreamFactory();
31 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_COMMENTS));
32 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS));
33 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES));
34 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_SINGLE_QUOTES));
35 }
36
3037 public void testQuotesRequired() throws Exception
3138 {
3239 _testQuotesRequired(false);
100107
101108 private void _testTabsEnabled(boolean useStream) throws Exception
102109 {
103 JsonFactory f = new JsonFactory();
104 f.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
110 JsonFactory f = JsonFactory.builder()
111 .configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS, true)
112 .build();
105113
106114 String FIELD = "a\tb";
107115 String VALUE = "\t";
141141 assertEquals("{ }|{ }|[ ]", _generateRoot(jf, new DefaultPrettyPrinter("|")));
142142 }
143143
144 // Alternative solution for [Issue#26]
144 // Alternative solution for [jackson-core#26]
145145 public void testCustomRootSeparatorWithFactory() throws Exception
146146 {
147 JsonFactory jf = new JsonFactory();
148 jf.setRootValueSeparator("##");
149 StringWriter sw = new StringWriter();
150 JsonGenerator gen = jf.createGenerator(sw);
147 JsonFactory f = ((JsonFactoryBuilder)JsonFactory.builder())
148 .rootValueSeparator("##")
149 .build();
150 StringWriter sw = new StringWriter();
151 JsonGenerator gen = f.createGenerator(sw);
151152 gen.writeNumber(13);
152153 gen.writeBoolean(false);
153154 gen.writeNull();
167168 _writeTestDocument(gen);
168169
169170 assertEquals("[3|\"abc\"|[true]|{\"f\"=null;\"f2\"=null}]", sw.toString());
171 gen.close();
170172 }
171173
172174 public void testCustomSeparatorsWithPP() throws Exception
179181 .withArrayValueSeparator('|')));
180182
181183 _writeTestDocument(gen);
184 gen.close();
182185
183186 assertEquals("[ 3| \"abc\"| [ true ]| {" + DefaultIndenter.SYS_LF +
184187 " \"f\" = null;" + DefaultIndenter.SYS_LF +
197200 .withoutSpacesInObjectEntries());
198201
199202 _writeTestDocument(gen);
203 gen.close();
200204
201205 assertEquals("[ 3| \"abc\"| [ true ]| {" + DefaultIndenter.SYS_LF +
202206 " \"f\"=null;" + DefaultIndenter.SYS_LF +
22 import java.io.*;
33
44 import com.fasterxml.jackson.core.*;
5 import com.fasterxml.jackson.core.json.JsonReadFeature;
56
67 /**
78 * Unit tests for verifying that support for (non-standard) comments
7172 }
7273
7374 public void testYAMLCommentsBytes() throws Exception {
74 JsonFactory f = new JsonFactory();
75 f.configure(JsonParser.Feature.ALLOW_YAML_COMMENTS, true);
75 final JsonFactory f = JsonFactory.builder()
76 .enable(JsonReadFeature.ALLOW_YAML_COMMENTS)
77 .build();
7678
7779 _testYAMLComments(f, MODE_INPUT_STREAM);
7880 _testCommentsBeforePropValue(f, MODE_INPUT_STREAM, "# foo\n");
8385 }
8486
8587 public void testYAMLCommentsChars() throws Exception {
86 JsonFactory f = new JsonFactory();
87 f.configure(JsonParser.Feature.ALLOW_YAML_COMMENTS, true);
88 final JsonFactory f = JsonFactory.builder()
89 .enable(JsonReadFeature.ALLOW_YAML_COMMENTS)
90 .build();
8891 _testYAMLComments(f, MODE_READER);
8992 final String COMMENT = "# foo\n";
9093 _testCommentsBeforePropValue(f, MODE_READER, COMMENT);
9295 }
9396
9497 public void testCCommentsBytes() throws Exception {
95 JsonFactory f = new JsonFactory();
96 f.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
98 final JsonFactory f = JsonFactory.builder()
99 .enable(JsonReadFeature.ALLOW_JAVA_COMMENTS)
100 .build();
97101 final String COMMENT = "/* foo */\n";
98102 _testCommentsBeforePropValue(f, MODE_INPUT_STREAM, COMMENT);
99103 _testCommentsBeforePropValue(f, MODE_INPUT_STREAM_THROTTLED, COMMENT);
101105 }
102106
103107 public void testCCommentsChars() throws Exception {
104 JsonFactory f = new JsonFactory();
105 f.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
108 final JsonFactory f = JsonFactory.builder()
109 .enable(JsonReadFeature.ALLOW_JAVA_COMMENTS)
110 .build();
106111 final String COMMENT = "/* foo */\n";
107112 _testCommentsBeforePropValue(f, MODE_READER, COMMENT);
108113 }
109114
110115 public void testCppCommentsBytes() throws Exception {
111 JsonFactory f = new JsonFactory();
112 f.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
116 final JsonFactory f = JsonFactory.builder()
117 .enable(JsonReadFeature.ALLOW_JAVA_COMMENTS)
118 .build();
113119 final String COMMENT = "// foo\n";
114120 _testCommentsBeforePropValue(f, MODE_INPUT_STREAM, COMMENT);
115121 _testCommentsBeforePropValue(f, MODE_INPUT_STREAM_THROTTLED, COMMENT);
117123 }
118124
119125 public void testCppCommentsChars() throws Exception {
120 JsonFactory f = new JsonFactory();
121 f.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
126 final JsonFactory f = JsonFactory.builder()
127 .enable(JsonReadFeature.ALLOW_JAVA_COMMENTS)
128 .build();
122129 final String COMMENT = "// foo \n";
123130 _testCommentsBeforePropValue(f, MODE_READER, COMMENT);
124131 }
276283 private JsonParser _createParser(String doc, int mode, boolean enabled)
277284 throws IOException
278285 {
279 JsonFactory f = new JsonFactory();
280 f.configure(JsonParser.Feature.ALLOW_COMMENTS, enabled);
286 final JsonFactory f = JsonFactory.builder()
287 .configure(JsonReadFeature.ALLOW_JAVA_COMMENTS, enabled)
288 .build();
281289 JsonParser p = createParser(f, mode, doc);
282290 assertToken(JsonToken.START_ARRAY, p.nextToken());
283291 return p;
4343
4444 private void _testIntern(boolean useStream, boolean enableIntern, String expName) throws IOException
4545 {
46 JsonFactory f = new JsonFactory();
47 f.configure(JsonFactory.Feature.INTERN_FIELD_NAMES, enableIntern);
46 JsonFactory f = JsonFactory.builder()
47 .configure(JsonFactory.Feature.INTERN_FIELD_NAMES, enableIntern)
48 .build();
4849 assertEquals(enableIntern, f.isEnabled(JsonFactory.Feature.INTERN_FIELD_NAMES));
4950 final String JSON = "{ \""+expName+"\" : 1}";
5051 JsonParser p = useStream ?
444445
445446 JsonParser p = JSON_FACTORY.createParser(input);
446447 assertEquals(JsonToken.START_ARRAY, p.nextToken());
447 // should also have skipped first 3 bytes of BOM; but do we have offset available?
448 /* 08-Oct-2013, tatu: Alas, due to [core#111], we have to omit BOM in calculations
449 * as we do not know what the offset is due to -- may need to revisit, if this
450 * discrepancy becomes an issue. For now it just means that BOM is considered
451 * "out of stream" (not part of input).
452 */
448
453449 JsonLocation loc = p.getTokenLocation();
454 // so if BOM was consider in-stream (part of input), this should expect 3:
455 assertEquals(0, loc.getByteOffset());
450 assertEquals(3, loc.getByteOffset());
456451 assertEquals(-1, loc.getCharOffset());
457452 assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken());
458453 assertEquals(JsonToken.END_ARRAY, p.nextToken());
0 package com.fasterxml.jackson.core.read;
1
2 import com.fasterxml.jackson.core.*;
3
4 // Tests mostly for [core#229]
5 public class LocationInArrayTest extends com.fasterxml.jackson.core.BaseTest
6 {
7 final JsonFactory JSON_F = new JsonFactory();
8
9 // for [core#229]
10 public void testOffsetInArraysBytes() throws Exception {
11 _testOffsetInArrays(true);
12 }
13
14 // for [core#229]
15 public void testOffsetInArraysChars() throws Exception {
16 _testOffsetInArrays(false);
17 }
18
19 private void _testOffsetInArrays(boolean useBytes) throws Exception
20 {
21 JsonParser p;
22 final String DOC = " [10, 251,\n 3 ]";
23
24 // first, char based:
25 p = useBytes ? JSON_F.createParser(DOC.getBytes("UTF-8"))
26 : JSON_F.createParser(DOC.toCharArray());
27 assertToken(JsonToken.START_ARRAY, p.nextToken());
28 _assertLocation(useBytes, p.getTokenLocation(), 2L, 1, 3);
29 _assertLocation(useBytes, p.getCurrentLocation(), 3L, 1, 4);
30
31 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
32 _assertLocation(useBytes, p.getTokenLocation(), 3L, 1, 4);
33 assertEquals(10, p.getIntValue()); // just to ensure read proceeds to end
34 // 2-digits so
35 _assertLocation(useBytes, p.getCurrentLocation(), 5L, 1, 6);
36
37 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
38 _assertLocation(useBytes, p.getTokenLocation(), 7L, 1, 8);
39 assertEquals(251, p.getIntValue()); // just to ensure read proceeds to end
40 _assertLocation(useBytes, p.getCurrentLocation(), 10L, 1, 11);
41
42 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
43 _assertLocation(useBytes, p.getTokenLocation(), 15L, 2, 4);
44 assertEquals(3, p.getIntValue());
45 _assertLocation(useBytes, p.getCurrentLocation(), 16L, 2, 5);
46
47 assertToken(JsonToken.END_ARRAY, p.nextToken());
48 _assertLocation(useBytes, p.getTokenLocation(), 18L, 2, 7);
49 _assertLocation(useBytes, p.getCurrentLocation(), 19L, 2, 8);
50
51 p.close();
52 }
53
54 private void _assertLocation(boolean useBytes, JsonLocation loc, long offset, int row, int col)
55 {
56 assertEquals(row, loc.getLineNr());
57 assertEquals(col, loc.getColumnNr());
58
59 if (useBytes) {
60 assertEquals(offset, loc.getByteOffset());
61 } else {
62 assertEquals(offset, loc.getCharOffset());
63 }
64 }
65 }
0 package com.fasterxml.jackson.core.read;
1
2 import com.fasterxml.jackson.core.*;
3
4 // tests for [core#37]
5 public class LocationInObjectTest extends BaseTest
6 {
7 public void testOffsetWithObjectFieldsUsingUTF8() throws Exception
8 {
9 final JsonFactory f = new JsonFactory();
10 byte[] b = "{\"f1\":\"v1\",\"f2\":{\"f3\":\"v3\"},\"f4\":[true,false],\"f5\":5}".getBytes("UTF-8");
11 // 1 6 11 16 17 22 28 33 34 39 46 51
12 JsonParser p = f.createParser(b);
13
14 assertEquals(JsonToken.START_OBJECT, p.nextToken());
15
16 assertEquals(JsonToken.FIELD_NAME, p.nextToken());
17 assertEquals(1L, p.getTokenLocation().getByteOffset());
18 assertEquals(JsonToken.VALUE_STRING, p.nextToken());
19 assertEquals(6L, p.getTokenLocation().getByteOffset());
20
21 assertEquals("f2", p.nextFieldName());
22 assertEquals(11L, p.getTokenLocation().getByteOffset());
23 assertEquals(JsonToken.START_OBJECT, p.nextValue());
24 assertEquals(16L, p.getTokenLocation().getByteOffset());
25
26 assertEquals("f3", p.nextFieldName());
27 assertEquals(17L, p.getTokenLocation().getByteOffset());
28 assertEquals(JsonToken.VALUE_STRING, p.nextValue());
29 assertEquals(22L, p.getTokenLocation().getByteOffset());
30 assertEquals(JsonToken.END_OBJECT, p.nextToken());
31
32 assertEquals("f4", p.nextFieldName());
33 assertEquals(28L, p.getTokenLocation().getByteOffset());
34 assertEquals(JsonToken.START_ARRAY, p.nextValue());
35 assertEquals(33L, p.getTokenLocation().getByteOffset());
36
37 assertEquals(JsonToken.VALUE_TRUE, p.nextValue());
38 assertEquals(34L, p.getTokenLocation().getByteOffset());
39
40 assertEquals(JsonToken.VALUE_FALSE, p.nextValue());
41 assertEquals(39L, p.getTokenLocation().getByteOffset());
42 assertEquals(JsonToken.END_ARRAY, p.nextToken());
43
44 assertEquals("f5", p.nextFieldName());
45 assertEquals(46L, p.getTokenLocation().getByteOffset());
46 assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken());
47 assertEquals(51L, p.getTokenLocation().getByteOffset());
48 assertEquals(JsonToken.END_OBJECT, p.nextToken());
49
50 p.close();
51 }
52
53 public void testOffsetWithObjectFieldsUsingReader() throws Exception
54 {
55 final JsonFactory f = new JsonFactory();
56 char[] c = "{\"f1\":\"v1\",\"f2\":{\"f3\":\"v3\"},\"f4\":[true,false],\"f5\":5}".toCharArray();
57 // 1 6 11 16 17 22 28 33 34 39 46 51
58 JsonParser p = f.createParser(c);
59
60 assertEquals(JsonToken.START_OBJECT, p.nextToken());
61
62 assertEquals(JsonToken.FIELD_NAME, p.nextToken());
63 assertEquals(1L, p.getTokenLocation().getCharOffset());
64 assertEquals(JsonToken.VALUE_STRING, p.nextToken());
65 assertEquals(6L, p.getTokenLocation().getCharOffset());
66
67 assertEquals("f2", p.nextFieldName());
68 assertEquals(11L, p.getTokenLocation().getCharOffset());
69 assertEquals(JsonToken.START_OBJECT, p.nextValue());
70 assertEquals(16L, p.getTokenLocation().getCharOffset());
71
72 assertEquals("f3", p.nextFieldName());
73 assertEquals(17L, p.getTokenLocation().getCharOffset());
74 assertEquals(JsonToken.VALUE_STRING, p.nextValue());
75 assertEquals(22L, p.getTokenLocation().getCharOffset());
76 assertEquals(JsonToken.END_OBJECT, p.nextToken());
77
78 assertEquals("f4", p.nextFieldName());
79 assertEquals(28L, p.getTokenLocation().getCharOffset());
80 assertEquals(JsonToken.START_ARRAY, p.nextValue());
81 assertEquals(33L, p.getTokenLocation().getCharOffset());
82
83 assertEquals(JsonToken.VALUE_TRUE, p.nextValue());
84 assertEquals(34L, p.getTokenLocation().getCharOffset());
85
86 assertEquals(JsonToken.VALUE_FALSE, p.nextValue());
87 assertEquals(39L, p.getTokenLocation().getCharOffset());
88 assertEquals(JsonToken.END_ARRAY, p.nextToken());
89
90 assertEquals("f5", p.nextFieldName());
91 assertEquals(46L, p.getTokenLocation().getCharOffset());
92 assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken());
93 assertEquals(51L, p.getTokenLocation().getCharOffset());
94 assertEquals(JsonToken.END_OBJECT, p.nextToken());
95
96 p.close();
97 }
98 }
0 package com.fasterxml.jackson.core.read;
1
2 import com.fasterxml.jackson.core.*;
3
4 public class LocationOffsetsTest extends com.fasterxml.jackson.core.BaseTest
5 {
6 final JsonFactory JSON_F = new JsonFactory();
7
8 // Trivially simple unit test for basics wrt offsets
9 public void testSimpleInitialOffsets() throws Exception
10 {
11 JsonLocation loc;
12 JsonParser p;
13 final String DOC = "{ }";
14
15 // first, char based:
16 p = JSON_F.createParser(DOC);
17 assertToken(JsonToken.START_OBJECT, p.nextToken());
18
19 loc = p.getTokenLocation();
20 assertEquals(-1L, loc.getByteOffset());
21 assertEquals(0L, loc.getCharOffset());
22 assertEquals(1, loc.getLineNr());
23 assertEquals(1, loc.getColumnNr());
24
25 loc = p.getCurrentLocation();
26 assertEquals(-1L, loc.getByteOffset());
27 assertEquals(1L, loc.getCharOffset());
28 assertEquals(1, loc.getLineNr());
29 assertEquals(2, loc.getColumnNr());
30
31 p.close();
32
33 // then byte-based
34
35 p = JSON_F.createParser(DOC.getBytes("UTF-8"));
36 assertToken(JsonToken.START_OBJECT, p.nextToken());
37
38 loc = p.getTokenLocation();
39 assertEquals(0L, loc.getByteOffset());
40 assertEquals(-1L, loc.getCharOffset());
41 assertEquals(1, loc.getLineNr());
42 assertEquals(1, loc.getColumnNr());
43
44 loc = p.getCurrentLocation();
45 assertEquals(1L, loc.getByteOffset());
46 assertEquals(-1L, loc.getCharOffset());
47 assertEquals(1, loc.getLineNr());
48 assertEquals(2, loc.getColumnNr());
49
50 p.close();
51 }
52
53 // for [core#111]
54 public void testOffsetWithInputOffset() throws Exception
55 {
56 JsonLocation loc;
57 JsonParser p;
58 // 3 spaces before, 2 after, just for padding
59 byte[] b = " { } ".getBytes("UTF-8");
60
61 // and then peel them off
62 p = JSON_F.createParser(b, 3, b.length-5);
63 assertToken(JsonToken.START_OBJECT, p.nextToken());
64
65 loc = p.getTokenLocation();
66 assertEquals(0L, loc.getByteOffset());
67 assertEquals(-1L, loc.getCharOffset());
68 assertEquals(1, loc.getLineNr());
69 assertEquals(1, loc.getColumnNr());
70
71 loc = p.getCurrentLocation();
72 assertEquals(1L, loc.getByteOffset());
73 assertEquals(-1L, loc.getCharOffset());
74 assertEquals(1, loc.getLineNr());
75 assertEquals(2, loc.getColumnNr());
76
77 p.close();
78 }
79
80 public void testOffsetWithoutInputOffset() throws Exception
81 {
82 JsonLocation loc;
83 JsonParser p;
84 // 3 spaces before, 2 after, just for padding
85 byte[] b = " { } ".getBytes("UTF-8");
86
87 // and then peel them off
88 p = JSON_F.createParser(b);
89 assertToken(JsonToken.START_OBJECT, p.nextToken());
90
91 loc = p.getTokenLocation();
92 assertEquals(3L, loc.getByteOffset());
93 assertEquals(-1L, loc.getCharOffset());
94 assertEquals(1, loc.getLineNr());
95 assertEquals(4, loc.getColumnNr());
96
97 loc = p.getCurrentLocation();
98 assertEquals(4L, loc.getByteOffset());
99 assertEquals(-1L, loc.getCharOffset());
100 assertEquals(1, loc.getLineNr());
101 assertEquals(5, loc.getColumnNr());
102
103 p.close();
104 }
105
106 // for [core#533]
107 public void testUtf8Bom() throws Exception
108 {
109 JsonLocation loc;
110 JsonParser p;
111
112 byte[] b = withUtf8Bom("{ }".getBytes());
113
114 // and then peel them off
115 p = JSON_F.createParser(b);
116 assertToken(JsonToken.START_OBJECT, p.nextToken());
117
118 loc = p.getTokenLocation();
119 assertEquals(3L, loc.getByteOffset());
120 assertEquals(-1L, loc.getCharOffset());
121 assertEquals(1, loc.getLineNr());
122 assertEquals(4, loc.getColumnNr());
123
124 loc = p.getCurrentLocation();
125 assertEquals(4L, loc.getByteOffset());
126 assertEquals(-1L, loc.getCharOffset());
127 assertEquals(1, loc.getLineNr());
128 assertEquals(5, loc.getColumnNr());
129
130 p.close();
131 }
132
133 public void testUtf8BomWithPadding() throws Exception
134 {
135 JsonLocation loc;
136 JsonParser p;
137
138 byte[] b = withUtf8Bom(" { }".getBytes());
139
140 // and then peel them off
141 p = JSON_F.createParser(b);
142 assertToken(JsonToken.START_OBJECT, p.nextToken());
143
144 loc = p.getTokenLocation();
145 assertEquals(6L, loc.getByteOffset());
146 assertEquals(-1L, loc.getCharOffset());
147 assertEquals(1, loc.getLineNr());
148 assertEquals(7, loc.getColumnNr());
149
150 loc = p.getCurrentLocation();
151 assertEquals(7L, loc.getByteOffset());
152 assertEquals(-1L, loc.getCharOffset());
153 assertEquals(1, loc.getLineNr());
154 assertEquals(8, loc.getColumnNr());
155
156 p.close();
157 }
158
159 public void testUtf8BomWithInputOffset() throws Exception
160 {
161 JsonLocation loc;
162 JsonParser p;
163
164 byte[] b = withUtf8Bom(" { }".getBytes());
165
166 // and then peel them off
167 p = JSON_F.createParser(b);
168 assertToken(JsonToken.START_OBJECT, p.nextToken());
169
170 loc = p.getTokenLocation();
171 assertEquals(6L, loc.getByteOffset());
172 assertEquals(-1L, loc.getCharOffset());
173 assertEquals(1, loc.getLineNr());
174 assertEquals(7, loc.getColumnNr());
175
176 loc = p.getCurrentLocation();
177 assertEquals(7L, loc.getByteOffset());
178 assertEquals(-1L, loc.getCharOffset());
179 assertEquals(1, loc.getLineNr());
180 assertEquals(8, loc.getColumnNr());
181
182 p.close();
183 }
184
185 private byte[] withUtf8Bom(byte[] bytes) {
186 byte[] arr = new byte[bytes.length + 3];
187 // write UTF-8 BOM
188 arr[0] = (byte) 0xEF;
189 arr[1] = (byte) 0xBB;
190 arr[2] = (byte) 0xBF;
191 System.arraycopy(bytes, 0, arr, 3, bytes.length);
192 return arr;
193 }
194 }
0 package com.fasterxml.jackson.core.read;
1
2 import com.fasterxml.jackson.core.JsonParser;
3 import com.fasterxml.jackson.core.JsonToken;
4
5 public class NextNameParserTest
6 extends com.fasterxml.jackson.core.BaseTest
7 {
8 public void testBasicNextNameWithReader() throws Exception
9 {
10 _testBasicNextName(MODE_READER);
11 }
12
13 public void testBasicNextNameWithStream() throws Exception
14 {
15 _testBasicNextName(MODE_INPUT_STREAM);
16 _testBasicNextName(MODE_INPUT_STREAM_THROTTLED);
17 }
18
19 private void _testBasicNextName(int mode) throws Exception
20 {
21 final String DOC = aposToQuotes(
22 "{ 'data' : { 'primary' : 15, 'vector' : [ 'yes', false ] },\n"
23 +" 'array' : [ true, {'message':'hello', 'value' : 42, 'misc' : [1, 2] }, null, 0.25 ]\n"
24 +"}");
25
26 JsonParser p = createParser(mode, DOC);
27
28 assertToken(JsonToken.START_OBJECT, p.nextToken());
29
30 assertToken(JsonToken.FIELD_NAME, p.nextToken());
31 assertEquals("data", p.currentName());
32 assertToken(JsonToken.START_OBJECT, p.nextToken());
33
34 assertEquals("primary", p.nextFieldName());
35 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
36 assertEquals(15, p.getIntValue());
37
38 assertEquals("vector", p.nextFieldName());
39 assertToken(JsonToken.START_ARRAY, p.nextToken());
40 assertToken(JsonToken.VALUE_STRING, p.nextToken());
41 assertEquals("yes", p.getText());
42 assertToken(JsonToken.VALUE_FALSE, p.nextToken());
43 assertToken(JsonToken.END_ARRAY, p.nextToken());
44
45 assertToken(JsonToken.END_OBJECT, p.nextToken());
46
47 assertEquals("array", p.nextFieldName());
48 assertToken(JsonToken.START_ARRAY, p.nextToken());
49 assertToken(JsonToken.VALUE_TRUE, p.nextToken());
50
51 assertToken(JsonToken.START_OBJECT, p.nextToken());
52 assertEquals("message", p.nextFieldName());
53 assertToken(JsonToken.VALUE_STRING, p.nextToken());
54 assertEquals("hello", p.getText());
55 assertEquals("value", p.nextFieldName());
56 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
57 assertEquals(42, p.getIntValue());
58 assertEquals("misc", p.nextFieldName());
59
60 assertToken(JsonToken.START_ARRAY, p.nextToken());
61 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
62 assertEquals(1, p.getIntValue());
63 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
64 assertEquals(2, p.getIntValue());
65 assertToken(JsonToken.END_ARRAY, p.nextToken());
66 assertToken(JsonToken.END_OBJECT, p.nextToken());
67
68 assertToken(JsonToken.VALUE_NULL, p.nextToken());
69 assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
70
71 assertToken(JsonToken.END_ARRAY, p.nextToken());
72
73 assertToken(JsonToken.END_OBJECT, p.nextToken());
74
75 p.close();
76 }
77 }
00 package com.fasterxml.jackson.core.read;
11
22 import com.fasterxml.jackson.core.*;
3 import com.fasterxml.jackson.core.json.JsonReadFeature;
34
45 public class NonStandardParserFeaturesTest
56 extends com.fasterxml.jackson.core.BaseTest
67 {
8 @SuppressWarnings("deprecation")
9 public void testDefaults() {
10 JsonFactory f = new JsonFactory();
11 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS));
12 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS));
13 }
14
715 public void testSingleQuotesDefault() throws Exception
816 {
917 _testSingleQuotesDefault(MODE_INPUT_STREAM);
7987 /****************************************************************
8088 */
8189
82
8390 /**
8491 * Test to verify that the default parser settings do not
8592 * accept single-quotes for String values (field names,
121128 */
122129 private void _testSingleQuotesEnabled(int mode) throws Exception
123130 {
124 JsonFactory f = new JsonFactory();
125 f.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
126
131 JsonFactory f = JsonFactory.builder()
132 .enable(JsonReadFeature.ALLOW_SINGLE_QUOTES)
133 .build();
127134 String JSON = "{ 'a' : 1, \"foobar\": 'b', '_abcde1234':'d', '\"' : '\"\"', '':'' }";
128135 JsonParser p = createParser(f, mode, JSON);
129136
198205 // test to verify that we implicitly allow escaping of apostrophe
199206 private void _testSingleQuotesEscaped(int mode) throws Exception
200207 {
201 JsonFactory f = new JsonFactory();
202 f.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
203
208 JsonFactory f = JsonFactory.builder()
209 .enable(JsonReadFeature.ALLOW_SINGLE_QUOTES)
210 .build();
204211 String JSON = "[ '16\\'' ]";
205212 JsonParser p = createParser(f, mode, JSON);
206213
213220
214221 private void _testNonStandardNameChars(int mode) throws Exception
215222 {
216 JsonFactory f = new JsonFactory();
217 f.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
223 final JsonFactory f = JsonFactory.builder()
224 .enable(JsonReadFeature.ALLOW_UNQUOTED_FIELD_NAMES)
225 .build();
218226 String JSON = "{ @type : \"mytype\", #color : 123, *error* : true, "
219227 +" hyphen-ated : \"yes\", me+my : null"
220228 +"}";
253261 {
254262 // first: verify that we get an exception
255263 JsonFactory f = new JsonFactory();
256 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER));
257264 final String JSON = quote("\\'");
258265 JsonParser p = createParser(f, mode, JSON);
259266 try {
266273 p.close();
267274 }
268275 // and then verify it's ok...
269 f.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);
270 assertTrue(f.isEnabled(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER));
276 f = f.rebuild()
277 .configure(JsonReadFeature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true)
278 .build();
271279 p = createParser(f, mode, JSON);
272280 assertToken(JsonToken.VALUE_STRING, p.nextToken());
273281 assertEquals("'", p.getText());
278286 {
279287 // first: verify that we get an exception
280288 JsonFactory f = new JsonFactory();
281 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS));
282289 String JSON = "00003";
283290 if (appendSpace) {
284291 JSON += " ";
293300 } finally {
294301 p.close();
295302 }
296
303
297304 // and then verify it's ok when enabled
298 f.configure(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS, true);
299 assertTrue(f.isEnabled(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS));
305 f = JsonFactory.builder()
306 .configure(JsonReadFeature.ALLOW_LEADING_ZEROS_FOR_NUMBERS, true)
307 .build();
300308 p = createParser(f, mode, JSON);
301309 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
302310 assertEquals(3, p.getIntValue());
321329 {
322330 final String JSON = "[ NaN]";
323331 JsonFactory f = new JsonFactory();
324 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS));
325332
326333 // without enabling, should get an exception
327334 JsonParser p = createParser(f, mode, JSON);
336343 }
337344
338345 // we can enable it dynamically (impl detail)
339 f.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true);
346 f = JsonFactory.builder()
347 .configure(JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS, true)
348 .build();
340349 p = createParser(f, mode, JSON);
341350 assertToken(JsonToken.START_ARRAY, p.nextToken());
342351 assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
357366 p.close();
358367
359368 // finally, should also work with skipping
360 f.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true);
369 f = JsonFactory.builder()
370 .configure(JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS, true)
371 .build();
361372 p = createParser(f, mode, JSON);
362373 assertToken(JsonToken.START_ARRAY, p.nextToken());
363374 assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
369380 {
370381 final String JSON = "[ -INF, +INF, +Infinity, Infinity, -Infinity ]";
371382 JsonFactory f = new JsonFactory();
372 assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS));
373383
374384 // without enabling, should get an exception
375385 JsonParser p = createParser(f, mode, JSON);
382392 } finally {
383393 p.close();
384394 }
385 f.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true);
395 f = JsonFactory.builder()
396 .enable(JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS)
397 .build();
386398 p = createParser(f, mode, JSON);
387399 assertToken(JsonToken.START_ARRAY, p.nextToken());
388400
420432 p.close();
421433
422434 // finally, should also work with skipping
423 f.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true);
435 f = JsonFactory.builder()
436 .configure(JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS, true)
437 .build();
424438 p = createParser(f, mode, JSON);
425439
426440 assertToken(JsonToken.START_ARRAY, p.nextToken());
22 import java.math.BigDecimal;
33 import java.math.BigInteger;
44
5 import com.fasterxml.jackson.core.BaseTest;
6 import com.fasterxml.jackson.core.JsonParseException;
7 import com.fasterxml.jackson.core.JsonParser;
5 import com.fasterxml.jackson.core.*;
86 import com.fasterxml.jackson.core.JsonParser.NumberType;
9 import com.fasterxml.jackson.core.JsonToken;
7 import com.fasterxml.jackson.core.exc.InputCoercionException;
108
119 public class NumberCoercionTest extends BaseTest
1210 {
6563 try {
6664 p.getIntValue();
6765 fail("Should not pass");
68 } catch (JsonParseException e) {
69 verifyException(e, "out of range of int");
66 } catch (InputCoercionException e) {
67 verifyException(e, "out of range of int");
68 assertEquals(JsonToken.VALUE_NUMBER_INT, e.getInputType());
69 assertEquals(Integer.TYPE, e.getTargetType());
7070 }
7171 long small = -1L + Integer.MIN_VALUE;
7272 p = createParser(mode, String.valueOf(small));
7676 try {
7777 p.getIntValue();
7878 fail("Should not pass");
79 } catch (JsonParseException e) {
80 verifyException(e, "out of range of int");
79 } catch (InputCoercionException e) {
80 verifyException(e, "out of range of int");
81 assertEquals(JsonToken.VALUE_NUMBER_INT, e.getInputType());
82 assertEquals(Integer.TYPE, e.getTargetType());
8183 }
8284
8385 // double -> error
8789 try {
8890 p.getIntValue();
8991 fail("Should not pass");
90 } catch (JsonParseException e) {
91 verifyException(e, "out of range of int");
92 } catch (InputCoercionException e) {
93 verifyException(e, "out of range of int");
94 assertEquals(JsonToken.VALUE_NUMBER_INT, e.getInputType());
95 assertEquals(Integer.TYPE, e.getTargetType());
9296 }
9397 p = createParser(mode, String.valueOf(small)+".0");
9498 assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
96100 try {
97101 p.getIntValue();
98102 fail("Should not pass");
99 } catch (JsonParseException e) {
100 verifyException(e, "out of range of int");
103 } catch (InputCoercionException e) {
104 verifyException(e, "out of range of int");
105 assertEquals(JsonToken.VALUE_NUMBER_INT, e.getInputType());
106 assertEquals(Integer.TYPE, e.getTargetType());
101107 }
102108
103109 // BigInteger -> error
107113 try {
108114 p.getIntValue();
109115 fail("Should not pass");
110 } catch (JsonParseException e) {
111 verifyException(e, "out of range of int");
116 } catch (InputCoercionException e) {
117 verifyException(e, "out of range of int");
118 assertEquals(JsonToken.VALUE_NUMBER_INT, e.getInputType());
119 assertEquals(Integer.TYPE, e.getTargetType());
112120 }
113121 p = createParser(mode, String.valueOf(small));
114122 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
116124 try {
117125 p.getIntValue();
118126 fail("Should not pass");
119 } catch (JsonParseException e) {
120 verifyException(e, "out of range of int");
127 } catch (InputCoercionException e) {
128 verifyException(e, "out of range of int");
129 assertEquals(JsonToken.VALUE_NUMBER_INT, e.getInputType());
130 assertEquals(Integer.TYPE, e.getTargetType());
121131 }
122132 }
123133 }
174184 try {
175185 p.getLongValue();
176186 fail("Should not pass");
177 } catch (JsonParseException e) {
187 } catch (InputCoercionException e) {
178188 verifyException(e, "out of range of long");
189 assertEquals(JsonToken.VALUE_NUMBER_INT, e.getInputType());
190 assertEquals(Long.TYPE, e.getTargetType());
179191 }
180192 BigInteger small = BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.TEN);
181193 p = createParser(mode, String.valueOf(small));
184196 try {
185197 p.getLongValue();
186198 fail("Should not pass");
187 } catch (JsonParseException e) {
199 } catch (InputCoercionException e) {
188200 verifyException(e, "out of range of long");
201 assertEquals(JsonToken.VALUE_NUMBER_INT, e.getInputType());
202 assertEquals(Long.TYPE, e.getTargetType());
189203 }
190204 }
191205 }
22 import java.math.BigInteger;
33
44 import com.fasterxml.jackson.core.*;
5 import com.fasterxml.jackson.core.exc.InputCoercionException;
56
67 public class NumberOverflowTest
78 extends com.fasterxml.jackson.core.BaseTest
3839 try {
3940 long x = p.getLongValue();
4041 fail("Expected an exception for underflow (input "+p.getText()+"): instead, got long value: "+x);
41 } catch (JsonParseException e) {
42 } catch (InputCoercionException e) {
4243 verifyException(e, "out of range of long");
4344 }
4445 p.close();
4849 try {
4950 long x = p.getLongValue();
5051 fail("Expected an exception for underflow (input "+p.getText()+"): instead, got long value: "+x);
51 } catch (JsonParseException e) {
52 } catch (InputCoercionException e) {
5253 verifyException(e, "out of range of long");
5354 }
5455 p.close();
6970 try {
7071 p.getLongValue();
7172 fail("Should not pass");
72 } catch (JsonParseException e) {
73 } catch (InputCoercionException e) {
7374 verifyException(e, "out of range of long");
7475 verifyException(e, "Integer with "+BIG_NUM_LEN+" digits");
7576 }
8990 try {
9091 p.getIntValue();
9192 fail("Should not pass");
92 } catch (JsonParseException e) {
93 } catch (InputCoercionException e) {
9394 verifyException(e, "out of range of int");
9495 verifyException(e, "Integer with "+BIG_NUM_LEN+" digits");
9596 }
66 import java.math.BigInteger;
77
88 import com.fasterxml.jackson.core.*;
9 import com.fasterxml.jackson.core.exc.InputCoercionException;
10 import com.fasterxml.jackson.core.json.JsonReadFeature;
911
1012 /**
1113 * Set of basic unit tests for verifying that the basic parser
123125 // Should get an exception if trying to convert to int
124126 try {
125127 p.getIntValue();
126 } catch (JsonParseException pe) {
127 verifyException(pe, "out of range");
128 } catch (InputCoercionException e) {
129 verifyException(e, "out of range");
130 assertEquals(JsonToken.VALUE_NUMBER_INT, e.getInputType());
131 assertEquals(Integer.TYPE, e.getTargetType());
128132 }
129133 assertEquals((double) EXP_L, p.getDoubleValue());
130134 assertEquals(BigDecimal.valueOf((long) EXP_L), p.getDecimalValue());
427431 */
428432 public void testParsingOfLongerSequencesWithNonNumeric() throws Exception
429433 {
430 JsonFactory f = new JsonFactory();
431 f.enable(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS);
434 JsonFactory f = JsonFactory.builder()
435 .enable(JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS)
436 .build();
432437 _testParsingOfLongerSequencesWithNonNumeric(f, MODE_INPUT_STREAM);
433438 _testParsingOfLongerSequencesWithNonNumeric(f, MODE_INPUT_STREAM_THROTTLED);
434439 _testParsingOfLongerSequencesWithNonNumeric(f, MODE_READER);
33 import java.util.*;
44
55 import com.fasterxml.jackson.core.*;
6 import com.fasterxml.jackson.core.JsonParser.Feature;
76 import com.fasterxml.jackson.core.io.SerializedString;
7 import com.fasterxml.jackson.core.json.JsonReadFeature;
88 import com.fasterxml.jackson.core.json.UTF8DataInputJsonParser;
99
1010 import org.junit.Test;
1212 import org.junit.runners.Parameterized;
1313
1414 @RunWith(Parameterized.class)
15 @SuppressWarnings("resource")
1516 public class TrailingCommasTest extends BaseTest {
1617
1718 private final JsonFactory factory;
18 private final Set<JsonParser.Feature> features;
19 private final Set<JsonReadFeature> features;
1920 private final int mode;
2021
21 public TrailingCommasTest(int mode, List<Feature> features) {
22 this.factory = new JsonFactory();
23 this.features = new HashSet<JsonParser.Feature>(features);
24
25 for (JsonParser.Feature feature : features) {
26 factory.enable(feature);
27 }
28
29 this.mode = mode;
22 public TrailingCommasTest(int mode, List<JsonReadFeature> features) {
23 this.features = new HashSet<JsonReadFeature>(features);
24 JsonFactoryBuilder b = (JsonFactoryBuilder) JsonFactory.builder();
25 for (JsonReadFeature feature : features) {
26 b = b.enable(feature);
27 }
28 factory = b.build();
29 this.mode = mode;
3030 }
3131
3232 @Parameterized.Parameters(name = "Mode {0}, Features {1}")
3535
3636 for (int mode : ALL_MODES) {
3737 cases.add(new Object[]{mode, Collections.emptyList()});
38 cases.add(new Object[]{mode, Arrays.asList(Feature.ALLOW_MISSING_VALUES)});
39 cases.add(new Object[]{mode, Arrays.asList(Feature.ALLOW_TRAILING_COMMA)});
40 cases.add(new Object[]{mode, Arrays.asList(Feature.ALLOW_MISSING_VALUES, Feature.ALLOW_TRAILING_COMMA)});
38 cases.add(new Object[]{mode, Arrays.asList(JsonReadFeature.ALLOW_MISSING_VALUES)});
39 cases.add(new Object[]{mode, Arrays.asList(JsonReadFeature.ALLOW_TRAILING_COMMA)});
40 cases.add(new Object[]{mode, Arrays.asList(JsonReadFeature.ALLOW_MISSING_VALUES,
41 JsonReadFeature.ALLOW_TRAILING_COMMA)});
4142 }
4243
4344 return cases;
4445 }
4546
46 @SuppressWarnings("resource")
4747 @Test
4848 public void testArrayBasic() throws Exception {
4949 String json = "[\"a\", \"b\"]";
6262 assertEnd(p);
6363 }
6464
65 @SuppressWarnings("resource")
6665 @Test
6766 public void testArrayInnerComma() throws Exception {
6867 String json = "[\"a\",, \"b\"]";
7473 assertToken(JsonToken.VALUE_STRING, p.nextToken());
7574 assertEquals("a", p.getText());
7675
77 if (!features.contains(Feature.ALLOW_MISSING_VALUES)) {
76 if (!features.contains(JsonReadFeature.ALLOW_MISSING_VALUES)) {
77 assertUnexpected(p, ',');
78 return;
79 }
80
81 assertToken(JsonToken.VALUE_NULL, p.nextToken());
82
83 assertToken(JsonToken.VALUE_STRING, p.nextToken());
84 assertEquals("b", p.getText());
85
86 assertEquals(JsonToken.END_ARRAY, p.nextToken());
87 assertEnd(p);
88 }
89
90 @Test
91 public void testArrayLeadingComma() throws Exception {
92 String json = "[,\"a\", \"b\"]";
93
94 JsonParser p = createParser(factory, mode, json);
95
96 assertEquals(JsonToken.START_ARRAY, p.nextToken());
97
98 if (!features.contains(JsonReadFeature.ALLOW_MISSING_VALUES)) {
7899 assertUnexpected(p, ',');
79100 return;
80101 }
82103 assertToken(JsonToken.VALUE_NULL, p.nextToken());
83104
84105 assertToken(JsonToken.VALUE_STRING, p.nextToken());
106 assertEquals("a", p.getText());
107
108 assertToken(JsonToken.VALUE_STRING, p.nextToken());
85109 assertEquals("b", p.getText());
86110
87111 assertEquals(JsonToken.END_ARRAY, p.nextToken());
88112 assertEnd(p);
89 }
90
91 @SuppressWarnings("resource")
92 @Test
93 public void testArrayLeadingComma() throws Exception {
94 String json = "[,\"a\", \"b\"]";
95
96 JsonParser p = createParser(factory, mode, json);
97
98 assertEquals(JsonToken.START_ARRAY, p.nextToken());
99
100 if (!features.contains(Feature.ALLOW_MISSING_VALUES)) {
101 assertUnexpected(p, ',');
102 return;
103 }
104
105 assertToken(JsonToken.VALUE_NULL, p.nextToken());
106
107 assertToken(JsonToken.VALUE_STRING, p.nextToken());
108 assertEquals("a", p.getText());
109
110 assertToken(JsonToken.VALUE_STRING, p.nextToken());
111 assertEquals("b", p.getText());
112
113 assertEquals(JsonToken.END_ARRAY, p.nextToken());
114 assertEnd(p);
115113 p.close();
116114 }
117115
130128 assertEquals("b", p.getText());
131129
132130 // ALLOW_TRAILING_COMMA takes priority over ALLOW_MISSING_VALUES
133 if (features.contains(Feature.ALLOW_TRAILING_COMMA)) {
134 assertToken(JsonToken.END_ARRAY, p.nextToken());
135 assertEnd(p);
136 } else if (features.contains(Feature.ALLOW_MISSING_VALUES)) {
131 if (features.contains(JsonReadFeature.ALLOW_TRAILING_COMMA)) {
132 assertToken(JsonToken.END_ARRAY, p.nextToken());
133 assertEnd(p);
134 } else if (features.contains(JsonReadFeature.ALLOW_MISSING_VALUES)) {
137135 assertToken(JsonToken.VALUE_NULL, p.nextToken());
138136 assertToken(JsonToken.END_ARRAY, p.nextToken());
139137 assertEnd(p);
158156 assertEquals("b", p.getText());
159157
160158 // ALLOW_TRAILING_COMMA takes priority over ALLOW_MISSING_VALUES
161 if (features.contains(Feature.ALLOW_MISSING_VALUES) &&
162 features.contains(Feature.ALLOW_TRAILING_COMMA)) {
163 assertToken(JsonToken.VALUE_NULL, p.nextToken());
164 assertToken(JsonToken.END_ARRAY, p.nextToken());
165 assertEnd(p);
166 } else if (features.contains(Feature.ALLOW_MISSING_VALUES)) {
159 if (features.contains(JsonReadFeature.ALLOW_MISSING_VALUES) &&
160 features.contains(JsonReadFeature.ALLOW_TRAILING_COMMA)) {
161 assertToken(JsonToken.VALUE_NULL, p.nextToken());
162 assertToken(JsonToken.END_ARRAY, p.nextToken());
163 assertEnd(p);
164 } else if (features.contains(JsonReadFeature.ALLOW_MISSING_VALUES)) {
167165 assertToken(JsonToken.VALUE_NULL, p.nextToken());
168166 assertToken(JsonToken.VALUE_NULL, p.nextToken());
169167 assertToken(JsonToken.END_ARRAY, p.nextToken());
189187 assertEquals("b", p.getText());
190188
191189 // ALLOW_TRAILING_COMMA takes priority over ALLOW_MISSING_VALUES
192 if (features.contains(Feature.ALLOW_MISSING_VALUES) &&
193 features.contains(Feature.ALLOW_TRAILING_COMMA)) {
194 assertToken(JsonToken.VALUE_NULL, p.nextToken());
195 assertToken(JsonToken.VALUE_NULL, p.nextToken());
196 assertToken(JsonToken.END_ARRAY, p.nextToken());
197 assertEnd(p);
198 } else if (features.contains(Feature.ALLOW_MISSING_VALUES)) {
190 if (features.contains(JsonReadFeature.ALLOW_MISSING_VALUES) &&
191 features.contains(JsonReadFeature.ALLOW_TRAILING_COMMA)) {
192 assertToken(JsonToken.VALUE_NULL, p.nextToken());
193 assertToken(JsonToken.VALUE_NULL, p.nextToken());
194 assertToken(JsonToken.END_ARRAY, p.nextToken());
195 assertEnd(p);
196 } else if (features.contains(JsonReadFeature.ALLOW_MISSING_VALUES)) {
199197 assertToken(JsonToken.VALUE_NULL, p.nextToken());
200198 assertToken(JsonToken.VALUE_NULL, p.nextToken());
201199 assertToken(JsonToken.VALUE_NULL, p.nextToken());
272270 assertEquals("b", p.getText());
273271 assertToken(JsonToken.VALUE_FALSE, p.nextToken());
274272
275 if (features.contains(Feature.ALLOW_TRAILING_COMMA)) {
273 if (features.contains(JsonReadFeature.ALLOW_TRAILING_COMMA)) {
276274 assertToken(JsonToken.END_OBJECT, p.nextToken());
277275 assertEnd(p);
278276 } else {
294292 assertEquals("b", p.nextFieldName());
295293 assertToken(JsonToken.VALUE_FALSE, p.nextToken());
296294
297 if (features.contains(Feature.ALLOW_TRAILING_COMMA)) {
295 if (features.contains(JsonReadFeature.ALLOW_TRAILING_COMMA)) {
298296 assertEquals(null, p.nextFieldName());
299297 assertToken(JsonToken.END_OBJECT, p.currentToken());
300298 assertEnd(p);
323321 assertTrue(p.nextFieldName(new SerializedString("b")));
324322 assertToken(JsonToken.VALUE_FALSE, p.nextToken());
325323
326 if (features.contains(Feature.ALLOW_TRAILING_COMMA)) {
324 if (features.contains(JsonReadFeature.ALLOW_TRAILING_COMMA)) {
327325 assertFalse(p.nextFieldName(new SerializedString("c")));
328326 assertToken(JsonToken.END_OBJECT, p.currentToken());
329327 assertEnd(p);
11
22 import java.io.*;
33 import java.lang.reflect.Field;
4 import java.util.Random;
45
56 import com.fasterxml.jackson.core.*;
67
119120 p.close();
120121 }
121122
123 // [core#548]
124 public void testQuadsIssue548()
125 {
126 Random r = new Random(42);
127 ByteQuadsCanonicalizer root = ByteQuadsCanonicalizer.createRoot();
128 ByteQuadsCanonicalizer canon = root.makeChild(JsonFactory.Feature.collectDefaults());
129
130 int n_collisions = 25;
131 int[] collisions = new int[n_collisions];
132
133 // generate collisions
134 {
135 int maybe = r.nextInt();
136 int hash = canon.calcHash(maybe);
137 int target = ((hash & (2048-1)) << 2);
138
139 for (int i = 0; i < collisions.length; ) {
140 maybe = r.nextInt();
141 hash = canon.calcHash(maybe);
142 int offset = ((hash & (2048-1)) << 2);
143
144 if (offset == target) {
145 collisions[i++] = maybe;
146 }
147 }
148 }
149
150 // fill spillover area until _needRehash is true.
151 for(int i = 0; i < 22 ; i++) {
152 canon.addName(Integer.toString(i), collisions[i]);
153 }
154 // canon._needRehash is now true, since the spillover is full
155
156 // release table to update tableinfo with canon's data
157 canon.release();
158
159 // new table pulls data from new tableinfo, that has a full spillover, but set _needRehash to false
160 canon = root.makeChild(JsonFactory.Feature.collectDefaults());
161
162 // canon._needRehash == false, so this will try to add another item to the spillover area, even though it is full
163 canon.addName(Integer.toString(22), collisions[22]);
164 }
165
122166 /*
123167 /**********************************************************
124168 /* Helper methods
3232 "@~~", "A_~", "A`_", "Aa@", "Ab!", "B@~", // "BA_", "BB@", "BC!", "C!~"
3333 };
3434 */
35
35
3636 public void testReaderCollisions() throws Exception
3737 {
3838 StringBuilder sb = new StringBuilder();
5252
5353 // First: attempt with exceptions turned on; should catch an exception
5454
55 JsonFactory jf = new JsonFactory();
56 JsonParser jp = jf.createParser(sb.toString());
57 jf.enable(JsonFactory.Feature.FAIL_ON_SYMBOL_HASH_OVERFLOW);
55 JsonFactory f = JsonFactory.builder()
56 .enable(JsonFactory.Feature.FAIL_ON_SYMBOL_HASH_OVERFLOW)
57 .build();
58 JsonParser p = f.createParser(sb.toString());
5859
5960 try {
60 while (jp.nextToken() != null) {
61 while (p.nextToken() != null) {
6162 ;
6263 }
6364 fail("Should have failed");
6465 } catch (IllegalStateException e) {
6566 verifyException(e, "hash collision");
6667 }
67 jp.close();
68 p.close();
6869
6970 // but then without feature, should pass
70 jf = new JsonFactory();
71 jf.disable(JsonFactory.Feature.FAIL_ON_SYMBOL_HASH_OVERFLOW);
72 jp = jf.createParser(sb.toString());
73 while (jp.nextToken() != null) {
71 f = JsonFactory.builder()
72 .disable(JsonFactory.Feature.FAIL_ON_SYMBOL_HASH_OVERFLOW)
73 .build();
74 p = f.createParser(sb.toString());
75 while (p.nextToken() != null) {
7476 ;
7577 }
76 jp.close();
78 p.close();
7779 }
7880
7981 /*
110112 * Helper class to use for generating substrings to use for substring
111113 * substitution collisions.
112114 */
113 public static class CollisionGenerator
115 static class CollisionGenerator
114116 {
115117 /* JDK uses 31, but Jackson `CharsToNameCanonicalizer.HASH_MULT`,
116118 * which for 2.3 is 33.
2121 for (int i = 0; i < COUNT; ++i) {
2222 String id = fieldNameFor(i);
2323 char[] ch = id.toCharArray();
24
2425 symbols.findSymbol(ch, 0, ch.length, symbols.calcHash(id));
2526 }
2627
3536 assertEquals(3431, symbols.collisionCount());
3637
3738 assertEquals(6, symbols.maxCollisionLength());
39
40 // and final validation
41 symbols.verifyInternalConsistency();
3842 }
3943
4044 public void testSyntheticWithBytesNew() throws IOException
8286 symbolsC.calcHash(name));
8387 assertNotNull(str);
8488 }
89 // validate further, just to make sure
90 symbolsC.verifyInternalConsistency();
91
8592 symbolsC.release();
8693 exp += 250;
8794 if (exp > CharsToNameCanonicalizer.MAX_ENTRIES_FOR_REUSE) {
8996 }
9097 assertEquals(exp, symbolsCRoot.size());
9198 }
99
100 // Note: can not validate root instance, is not set up same way
92101 }
93102
94103 // Since 2.6
121130 }
122131 assertEquals(exp, symbolsBRoot.size());
123132 }
124 /* 05-Feb-2015, tatu: Fragile, but it is important to ensure that collision
125 * rates are not accidentally increased...
126 */
133
134 // 05-Feb-2015, tatu: Fragile, but it is important to ensure that collision
135 // rates are not accidentally increased...
127136 assertEquals(6250, symbolsB.size());
128137 assertEquals(4761, symbolsB.primaryCount()); // 80% primary hit rate
129138 assertEquals(1190, symbolsB.secondaryCount()); // 13% secondary
66
77 import com.fasterxml.jackson.core.JsonParser;
88 import com.fasterxml.jackson.core.JsonParser.NumberType;
9 import com.fasterxml.jackson.core.JsonStreamContext;
910 import com.fasterxml.jackson.core.JsonToken;
1011
1112 public abstract class AsyncReaderWrapper
5253
5354 public abstract JsonToken nextToken() throws IOException;
5455
56 public JsonStreamContext getParsingContext() {
57 return _streamReader.getParsingContext();
58 }
59
5560 public int getIntValue() throws IOException { return _streamReader.getIntValue(); }
5661 public long getLongValue() throws IOException { return _streamReader.getLongValue(); }
5762 public float getFloatValue() throws IOException { return _streamReader.getFloatValue(); }
66 /**
77 * Unit tests for class {@link RequestPayload}.
88 *
9 * @date 2017-07-31
109 * @see RequestPayload
1110 **/
1211 public class RequestPayloadTest {
13
12 @SuppressWarnings("unused")
1413 @Test(expected = IllegalArgumentException.class)
1514 public void testFailsToCreateTakingCharSequenceThrowsIllegalArgumentExceptionOne() {
16 new RequestPayload(null);
15 new RequestPayload(null);
1716 }
1817
18 @SuppressWarnings("unused")
1919 @Test(expected = IllegalArgumentException.class)
2020 public void testFailsToCreateTakingCharSequenceThrowsIllegalArgumentExceptionTwo() {
21 new RequestPayload(null, "UTF-8");
21 new RequestPayload(null, "UTF-8");
2222 }
2323
2424 @Test
158158 }
159159 return sw.toString();
160160 }
161
162 // [core#502]: Force sub-classes to reimplement `createInstance`
163 public void testInvalidSubClass() throws Exception
164 {
165 DefaultPrettyPrinter pp = new MyPrettyPrinter();
166 try {
167 pp.createInstance();
168 fail("Should not pass");
169 } catch (IllegalStateException e) {
170 verifyException(e, "does not override");
171 }
172 }
173
174 @SuppressWarnings("serial")
175 static class MyPrettyPrinter extends DefaultPrettyPrinter { }
161176 }
2828 return null;
2929 }
3030 @Override
31 public <T> T readValue(JsonParser p, TypeReference<?> valueTypeRef) {
31 public <T> T readValue(JsonParser p, TypeReference<T> valueTypeRef) {
3232 return null;
3333 }
3434 @Override
4141 }
4242 @Override
4343 public <T> Iterator<T> readValues(JsonParser p,
44 TypeReference<?> valueTypeRef) throws IOException {
44 TypeReference<T> valueTypeRef) throws IOException {
4545 return null;
4646 }
4747 @Override
7070 }
7171 @Override
7272 public TreeNode createArrayNode() {
73 return null;
74 }
75 @Override
76 public TreeNode missingNode() {
77 return null;
78 }
79
80 @Override
81 public TreeNode nullNode() {
7382 return null;
7483 }
7584 @Override
101101 public void testGetCurrentSegment() {
102102 TextBuffer textBuffer = new TextBuffer(null);
103103 textBuffer.emptyAndGetCurrentSegment();
104 textBuffer.setCurrentAndReturn(1000);
104 // 26-Aug-2019, tatu: Value depends on "minimum segment size":
105 textBuffer.setCurrentAndReturn(500);
105106 textBuffer.getCurrentSegment();
106107
107 assertEquals(1000, textBuffer.size());
108 assertEquals(500, textBuffer.size());
108109 }
109110
110111 public void testAppendTakingTwoAndThreeInts() {
0 package com.fasterxml.jackson.failing;
1
2 import com.fasterxml.jackson.core.JsonLocation;
3 import com.fasterxml.jackson.core.JsonParser;
4 import com.fasterxml.jackson.core.JsonToken;
5
6 public class LocationOffsets455Test extends com.fasterxml.jackson.core.BaseTest
7 {
8 // for [jackson-core#455]
9 public void testEOFLocationViaReader() throws Exception
10 {
11 JsonParser p = createParserUsingReader("42");
12 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
13 assertEquals(42, p.getIntValue());
14 JsonLocation loc = p.getCurrentLocation();
15 assertEquals(1, loc.getLineNr());
16 assertEquals(3, loc.getColumnNr());
17 assertEquals(2, loc.getByteOffset());
18
19 assertNull(p.nextToken());
20
21 loc = p.getCurrentLocation();
22 System.err.println("LOC/r = "+loc);
23 assertEquals(1, loc.getLineNr());
24 assertEquals(2, loc.getByteOffset());
25 assertEquals(3, loc.getColumnNr());
26 p.close();
27 }
28
29 // for [jackson-core#455]
30 public void testEOFLocationViaStream() throws Exception
31 {
32 JsonParser p = createParserUsingStream("42", "UTF-8");
33 assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
34 assertEquals(42, p.getIntValue());
35 JsonLocation loc = p.getCurrentLocation();
36 assertEquals(1, loc.getLineNr());
37 assertEquals(3, loc.getColumnNr());
38 assertEquals(2, loc.getByteOffset());
39
40 assertNull(p.nextToken());
41 loc = p.getCurrentLocation();
42 System.err.println("LOC/str = "+loc);
43 assertEquals(1, loc.getLineNr());
44 assertEquals(2, loc.getCharOffset());
45 assertEquals(3, loc.getColumnNr());
46 p.close();
47 }
48
49 }
+0
-124
src/test/java/com/fasterxml/jackson/failing/LocationOffsets533Test.java less more
0 package com.fasterxml.jackson.failing;
1
2 import com.fasterxml.jackson.core.*;
3
4 // For checking [databind#533]
5 public class LocationOffsets533Test extends com.fasterxml.jackson.core.BaseTest
6 {
7 final JsonFactory JSON_F = new JsonFactory();
8
9 public void testOffsetWithoutInputOffset() throws Exception
10 {
11 JsonLocation loc;
12 JsonParser p;
13 // 3 spaces before, 2 after, just for padding
14 byte[] b = " { } ".getBytes("UTF-8");
15
16 // and then peel them off
17 p = JSON_F.createParser(/*ObjectReadContext.empty(),*/ b);
18 assertToken(JsonToken.START_OBJECT, p.nextToken());
19
20 loc = p.getTokenLocation();
21 assertEquals(3L, loc.getByteOffset());
22 assertEquals(-1L, loc.getCharOffset());
23 assertEquals(1, loc.getLineNr());
24 assertEquals(4, loc.getColumnNr());
25
26 loc = p.getCurrentLocation();
27 assertEquals(4L, loc.getByteOffset());
28 assertEquals(-1L, loc.getCharOffset());
29 assertEquals(1, loc.getLineNr());
30 assertEquals(5, loc.getColumnNr());
31
32 p.close();
33 }
34
35 // for [core#533]
36 public void testUtf8Bom() throws Exception
37 {
38 JsonLocation loc;
39 JsonParser p;
40
41 byte[] b = withUtf8Bom("{ }".getBytes());
42
43 // and then peel them off
44 p = JSON_F.createParser(/*ObjectReadContext.empty(),*/ b);
45 assertToken(JsonToken.START_OBJECT, p.nextToken());
46
47 loc = p.getTokenLocation();
48 assertEquals(3L, loc.getByteOffset());
49 assertEquals(-1L, loc.getCharOffset());
50 assertEquals(1, loc.getLineNr());
51 assertEquals(4, loc.getColumnNr());
52
53 loc = p.getCurrentLocation();
54 assertEquals(4L, loc.getByteOffset());
55 assertEquals(-1L, loc.getCharOffset());
56 assertEquals(1, loc.getLineNr());
57 assertEquals(5, loc.getColumnNr());
58
59 p.close();
60 }
61
62 public void testUtf8BomWithPadding() throws Exception
63 {
64 JsonLocation loc;
65 JsonParser p;
66
67 byte[] b = withUtf8Bom(" { }".getBytes());
68
69 // and then peel them off
70 p = JSON_F.createParser(/*ObjectReadContext.empty(),*/ b);
71 assertToken(JsonToken.START_OBJECT, p.nextToken());
72
73 loc = p.getTokenLocation();
74 assertEquals(6L, loc.getByteOffset());
75 assertEquals(-1L, loc.getCharOffset());
76 assertEquals(1, loc.getLineNr());
77 assertEquals(7, loc.getColumnNr());
78
79 loc = p.getCurrentLocation();
80 assertEquals(7L, loc.getByteOffset());
81 assertEquals(-1L, loc.getCharOffset());
82 assertEquals(1, loc.getLineNr());
83 assertEquals(8, loc.getColumnNr());
84
85 p.close();
86 }
87
88 public void testUtf8BomWithInputOffset() throws Exception
89 {
90 JsonLocation loc;
91 JsonParser p;
92
93 byte[] b = withUtf8Bom(" { }".getBytes());
94
95 // and then peel them off
96 p = JSON_F.createParser(/*ObjectReadContext.empty(),*/ b);
97 assertToken(JsonToken.START_OBJECT, p.nextToken());
98
99 loc = p.getTokenLocation();
100 assertEquals(6L, loc.getByteOffset());
101 assertEquals(-1L, loc.getCharOffset());
102 assertEquals(1, loc.getLineNr());
103 assertEquals(7, loc.getColumnNr());
104
105 loc = p.getCurrentLocation();
106 assertEquals(7L, loc.getByteOffset());
107 assertEquals(-1L, loc.getCharOffset());
108 assertEquals(1, loc.getLineNr());
109 assertEquals(8, loc.getColumnNr());
110
111 p.close();
112 }
113
114 private byte[] withUtf8Bom(byte[] bytes) {
115 byte[] arr = new byte[bytes.length + 3];
116 // write UTF-8 BOM
117 arr[0] = (byte) 0xEF;
118 arr[1] = (byte) 0xBB;
119 arr[2] = (byte) 0xBF;
120 System.arraycopy(bytes, 0, arr, 3, bytes.length);
121 return arr;
122 }
123 }