pax_global_header00006660000000000000000000000064132320033510014502gustar00rootroot0000000000000052 comment=52bbbbc106af79c5aae6dc7cb8262711f89631a9 jackson-jr-jackson-jr-parent-2.9.4/000077500000000000000000000000001323200335100171055ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/.gitattributes000066400000000000000000000001371323200335100220010ustar00rootroot00000000000000# Do not merge `pom.xml` from older version, as it will typically conflict pom.xml merge=ours jackson-jr-jackson-jr-parent-2.9.4/.gitignore000066400000000000000000000002451323200335100210760ustar00rootroot00000000000000# use glob syntax. syntax: glob *.class *~ *.bak *.off *.old .DS_Store # building target # Eclipse .classpath .project .settings # IDEA *.iml *.ipr *.iws /target jackson-jr-jackson-jr-parent-2.9.4/.travis.yml000066400000000000000000000004111323200335100212120ustar00rootroot00000000000000language: java # 07-Sep-2017, tatu: Alas, jdk6 just doesn't work. First was missing JDK6 pkg # but then Maven itself, or one of plugins, compiled with later. So... just leave jdk: - openjdk7 - openjdk8 # whitelist branches: only: - master - "2.8" jackson-jr-jackson-jr-parent-2.9.4/LICENSE000066400000000000000000000240411323200335100201130ustar00rootroot00000000000000Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: You must give any other recipients of the Work or Derivative Works a copy of this License; and You must cause any modified files to carry prominent notices stating that You changed the files; and You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. jackson-jr-jackson-jr-parent-2.9.4/README.md000066400000000000000000000216241323200335100203710ustar00rootroot00000000000000# Overview Jackson jr is a compact alternative to full [Jackson Databind](../../../jackson-databind) component. It implements a subset of functionality, for example for cases where: 1. Size of jar matters (jackson-jr size is about 95kB) 2. Startup time matters (jackson-jr has very low initialization overhead) In addition to basic datatypes (core JDK types like `List`s, `Map`s, wrapper types), package supports reading and writing of standard Java Beans (implementation that mimics standard JDK Bean Introspection): that is, subset of POJOs that define setters/getters (starting with Jackson-jr `2.8`) you can alternatively use `public` fields). Jackson jr also adds `composer` implementation that can be used to construct JSON output with builder-style API, but without necessarily having to build an in-memory representation: instead, it can directly use `streaming-api` for direct output. It is also possible to build actual in-memory JSON `String` or `byte[]` representation, if that is preferable. Jackson jr artifact itself is currently about 95 kB in size, and only depends on [Jackson Streaming API](../../../jackson-core) package. Combined size, for "all" jar, is about 400 kB (of which streaming API is about 300 kB), for use cases where a single jar is preferred over more modular approach. Finally, use of jar minimizers like [ProGuard](http://proguard.sourceforge.net/) can bring the jar size down even further, by renaming and removing debug information. ## License Good old [Apache License](http://www.apache.org/licenses/LICENSE-2.0). ## Packaging Project is composed of multiple Maven sub-modules, each corresponding to a jar: * [jr-objects](../../tree/master/jr-objects) contains the "core" databinding implementation, and is commonly the only dependency to use * Depends on `jackson-core` for low-level reading/writing * [jr-stree](../../tree/master/jr-stree) contains a simple `TreeCodec` implementation, with which it is possible to read JSON as `TreeNode`s (see more below) * [jr-retrofit2](../../tree/master/jr-retrofit2) contains `jackson-jr` - based handlers for [Retrofit 2](http://square.github.io/retrofit/) library * Depends on `jackson-jr` and `Retrofit` API jars, and indirectly on `jackson-core` * jr-all creates an "uber-jar" that contains individual modules along with all their dependencies: * `jr-objects` classes as-is, without relocating * `jr-stree` classes as-is, without relocating * Jackson streaming (`jackson-core`) contents *relocated* ("shaded"), for private use by `jackson-jr` * Does NOT contain `jr-retrofit2` component If you are not sure which package to use, the answer is usually `jr-objects`, and build system (maven, gradle) will fetch the dependency needed. `jr-all` jar is only used if the single-jar deployment (self-contained, no external dependencies) is needed. ## Status [![Build Status](https://travis-ci.org/FasterXML/jackson-jr.svg)](https://travis-ci.org/FasterXML/jackson-jr) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.fasterxml.jackson.jr/jackson-jr-objects/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.fasterxml.jackson.jr/jackson-jr-objects/) [![Javadoc](https://javadoc-emblem.rhcloud.com/doc/com.fasterxml.jackson.jr/jackson-jr-objects/badge.svg)](http://www.javadoc.io/doc/com.fasterxml.jackson.jr/jackson-jr-objects) ## Usage ### Reading/writing Simple Objects, Beans, List/arrays thereof Functionality of this package is contained in Java package `com.fasterxml.jackson.jr.ob`. All functionality is accessed through main `JSON` Object; you can either used singleton `JSON.std`, or construct individual objects -- either way, `JSON` instances are ALWAYS immutable and hence thread-safe. We can start by reading JSON ```java String INPUT = "{\"a\":[1,2,{\"b\":true},3],\"c\":3}"; Object ob = JSON.std.anyFrom(INPUT); // or Map map = JSON.std.mapFrom(INPUT); // or MyBean bean = JSON.std.beanFrom(MyBean.class, INPUT); ``` from any of the usual input sources (`InputStream`, `Reader`, `String` or `byte[]` that contains JSON, `URL`, `JsonParser`); and can write same Objects as JSON: ```java String json = JSON.std.asString(map); JSON.std.write(ob, new File("/tmp/stuff.json"); // and with indentation; but skip writing of null properties byte[] bytes = JSON.std .with(Feature.PRETTY_PRINT_OUTPUT) .without(Feature.WRITE_NULL_PROPERTIES) .asBytes(bean); ``` and may also read `List`s and arrays of simple and Bean types: ```java List beans = JSON.std.listOfFrom(MyType.class, INPUT); ``` (writing of `List`s and arrays works without addition effort: just pass List/array as-is) ### Writing with composers An alternative method exists for writing: "fluent" style output can be used as follows: ```java String json = JSON.std .with(JSON.Feature.PRETTY_PRINT_OUTPUT) .composeString() .startObject() .put("a", 1) .startArrayField("arr") .add(1).add(2).add(3) .end() .startObjectField("ob") .put("x", 3) .put("y", 4) .startArrayField("args").add("none").end() .end() .put("last", true) .end() .finish(); ``` would produce (since pretty-printing is enabled) ```json { "a" : 1, "arr" : [1,2,3], "ob" : { "x" : 3, "y" : 4, "args" : ["none"] }, "last" : true } ``` ### Reading/writing JSON Trees Jackson jr allows pluggable "tree models", and also provides one implementation, `jr-stree`. Usage for `jr-stree` is by configuring `JSON` with codec, and then using `treeFrom` and `write` methods like so: ```java JSON json = JSON.std.with(new JacksonJrsTreeCodec()); TreeNode root = json.treeFrom("{\"value\" : [1, 2, 3]}"); assertTrue(root.isObject()); TreeNode array = root.get("value"); assertTrue(array.isArray()); JrsNumber n = (JrsNumber) array.get(1); assertEquals(2, n.getValue().intValue()); String json = json.asString(root); ``` Note that `jr-stree` implementation is a small minimalistic implementation with immutable nodes. It is most useful for simple reading use cases. It is however possible to write your own `TreeCodec` implementations that integrate seamlessly, and in future other tree models may be offered as part of jackson-jr, or via other libraries. ### Designing your Beans To support readability and writability of your own types, your Java objects must either: * Implement Bean style accesors (getters for accessing data to write and/or setter for binding JSON data into objects), and define no-argument (default) constructor, OR * Define single-argument constructor if binding from JSON String (single-String argument) or JSON integer number (single-`long` or `Long` argument) Note that although getters and setters need to be public (since JDK Bean Introspection does not find any other methods), constructors may have any access right, including `private`. Also: starting with version 2.8, `public` fields may also be used (although their discovery may be disabled using `JSON.Feature.USE_FIELDS`) as an alternative: this is useful when limiting number of otherwise useless "getter" and "setter" methods. ### Customizing behavior with Features There are many customizable features you can use with `JSON` object; see [Full List of Features](../../wiki/JSON-Features) for details. But usage itself is via fluent methods like so: ```java String json = JSON.std .with(JSON.Feature.PRETTY_PRINT_OUTPUT) .without(JSON.Feature.FAIL_ON_DUPLICATE_MAP_KEYS) .asString(...); ``` ## Get it! You can use Maven dependency like: ```xml com.fasterxml.jackson.jr jackson-jr-objects 2.9.0 ``` and then you can also download jars via [Central Maven repository](http://repo1.maven.org/maven2/com/fasterxml/jackson/jr/jackson-jr-objects/). Or you can also clone the project and build it locally with `mvn clean install`. Alternatively if you want a single jar deployment, you can use `jackson-jr-all` jar which embeds `jackson-core` (repackaged using Shade plug-in, so as not to conflict with "vanilla" `jackson-core`): http://repo1.maven.org/maven2/com/fasterxml/jackson/jr/jackson-jr-all/ ## Performance Initial performance testing using [JVM Serializers](https://github.com/eishay/jvm-serializers/wiki) benchmark suggests that it is almost as fast as [full Jackson databind](https://github.com/FasterXML/jackson-databind) -- additional overhead for tests is 5-10% for both serialization and deserialization. So performance is practically identical. In fact, when only handling `List`s and `Map`s style content, speed `jackson-jr` speed fully matches `jackson-databind` performance (Bean/POJO case is where full databinding's extensive optimizations help more). So performance should be adequate, and choice should be more based on functionality, convenience and deployment factors. About the only thing missing is that there is no equivalent to [Afterburner](../../../jackson-module-afterburner), which can further speed up databind by 20-30%, for most performance-sensitive systems. jackson-jr-jackson-jr-parent-2.9.4/jr-all/000077500000000000000000000000001323200335100202665ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-all/.gitignore000066400000000000000000000000101323200335100222450ustar00rootroot00000000000000/target jackson-jr-jackson-jr-parent-2.9.4/jr-all/pom.xml000066400000000000000000000076531323200335100216160ustar00rootroot00000000000000 4.0.0 com.fasterxml.jackson.jr jackson-jr-parent 2.9.4 jackson-jr-all jackson-jr-all jar "Uber" jar that contains all Jackson jr components as well as underlying Jackson core Streaming, in a single jar. http://wiki.fasterxml.com/JacksonHome com.fasterxml.jackson.jr jackson-jr-objects ${project.version} com.fasterxml.jackson.jr jackson-jr-stree ${project.version} org.apache.maven.plugins maven-shade-plugin ${version.plugin.shade} true *:* META-INF/*.SF META-INF/*.DSA META-INF/*.RSA jrall/*.class com.fasterxml.jackson.core com.fasterxml.jackson.jr.private_ package shade true org.apache.maven.plugins maven-javadoc-plugin package jar true com.fasterxml.jackson.jr:* com.fasterxml.jackson.jr.private_.* jackson-jr-jackson-jr-parent-2.9.4/jr-objects/000077500000000000000000000000001323200335100211475ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/.gitignore000066400000000000000000000000101323200335100231260ustar00rootroot00000000000000/target jackson-jr-jackson-jr-parent-2.9.4/jr-objects/pom.xml000066400000000000000000000070561323200335100224740ustar00rootroot00000000000000 4.0.0 com.fasterxml.jackson.jr jackson-jr-parent 2.9.4 jackson-jr-objects bundle Simple data-binding that builds directly on jackson-core (streaming), has no other dependencies, and provides additional builder-style content generator http://wiki.fasterxml.com/JacksonHome com/fasterxml/jackson/jr/ob ${project.groupId}.ob ${basedir}/src/main/java/${packageVersion.dir}/PackageVersion.java.in ${generatedSourcesDir}/${packageVersion.dir}/PackageVersion.java com.fasterxml.jackson.core jackson-core ${jackson.version.core} org.apache.maven.plugins maven-javadoc-plugin ${version.plugin.javadoc} http://docs.oracle.com/javase/7/docs/api/ http://fasterxml.github.com/jackson-core/javadoc/2.7 com.google.code.maven-replacer-plugin replacer process-packageVersion replace generate-sources ${packageVersion.template.input} ${packageVersion.template.output} @package@ ${packageVersion.package} @projectversion@ ${project.version} @projectgroupid@ ${project.groupId} @projectartifactid@ ${project.artifactId} org.apache.maven.plugins maven-surefire-plugin ${surefire.redirectTestOutputToFile} **/failing/*.java jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/000077500000000000000000000000001323200335100217365ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/000077500000000000000000000000001323200335100226625ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/000077500000000000000000000000001323200335100236035ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/000077500000000000000000000000001323200335100243615ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/000077500000000000000000000000001323200335100263665ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/000077500000000000000000000000001323200335100300165ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/000077500000000000000000000000001323200335100304315ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/000077500000000000000000000000001323200335100310315ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/JSON.java000066400000000000000000001172101323200335100324470ustar00rootroot00000000000000package com.fasterxml.jackson.jr.ob; import java.io.*; import java.net.URL; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.SegmentedStringWriter; import com.fasterxml.jackson.core.util.ByteArrayBuilder; import com.fasterxml.jackson.core.util.Instantiatable; import com.fasterxml.jackson.jr.ob.comp.CollectionComposer; import com.fasterxml.jackson.jr.ob.comp.ComposerBase; import com.fasterxml.jackson.jr.ob.comp.MapComposer; import com.fasterxml.jackson.jr.ob.impl.*; /** * Main entry point for functionality. *

* Note that instances are fully immutable, and thereby thread-safe. */ @SuppressWarnings("resource") public class JSON implements Versioned { /** * Simple on/off (enabled/disabled) features for {@link JSON}; used for simple configuration * aspects. */ public enum Feature { /* /********************************************************************** /* Read-related features that do not affect caching /********************************************************************** */ /** * When reading JSON Numbers, should {@link java.math.BigDecimal} be used * for floating-point numbers; or should {@link java.lang.Double} be used. * Trade-off is between accuracy -- only {@link java.math.BigDecimal} is * guaranteed to store the EXACT decimal value parsed -- and performance * ({@link java.lang.Double} is typically faster to parse). *

* Default setting is false, meaning that {@link java.lang.Double} * is used. */ USE_BIG_DECIMAL_FOR_FLOATS(false), /** * When reading JSON Arrays, should matching Java value be of type * Object[] (true) or {@link java.util.List} (false)? *

* Default setting is false, meaning that JSON Arrays * are bound to {@link java.util.List}s. */ READ_JSON_ARRAYS_AS_JAVA_ARRAYS(false), /** * This feature can be enabled to reduce memory usage for use cases where * resulting container objects ({@link java.util.Map}s and {@link java.util.Collection}s) * do not need to mutable (that is, their contents can not changed). * If set, reader is allowed to construct immutable (read-only) * container objects; and specifically empty {@link java.util.Map}s and * {@link java.util.Collection}s can be used to reduce number of * objects allocated. In addition, sizes of non-empty containers can * be trimmed to exact size. *

* Default setting is false, meaning that reader will have to * construct mutable container instance when reading. */ READ_ONLY(false), /** * This feature can be used to indicate that the reader should preserve * order of the properties same as what input document has. * Note that it is up to {@link com.fasterxml.jackson.jr.ob.impl.MapBuilder} * to support this feature; custom implementations may ignore the setting. *

* Default setting is true, meaning that reader is expected to try to * preserve ordering of fields read. */ PRESERVE_FIELD_ORDERING(true), /** * This feature determines whether {@link Map} instances constructed use * deferred materialization (as implemented by {@link DeferredMap}), in case * user has not specified custom {@link Map} implementation. * Enabling feature typically reduces initial value read time and moves * overhead to actual access of contents (materialization occurs when first * key or value access happens); this makes sense when only a subset of * data is accessed. Conversely, when traversing full object hierarchy, it * makes sense to disable this feature. *

* Default setting is true, meaning that reader is expected to try to */ USE_DEFERRED_MAPS(true), /** * When encountering duplicate keys for JSON Objects, should an exception * be thrown or not? If exception is not thrown, the last instance * from input document will be used. *

* Default setting is true, meaning that a * {@link JSONObjectException} will be thrown if duplicates are encountered. */ FAIL_ON_DUPLICATE_MAP_KEYS(true), /** * When encountering a JSON Object property name for which there is no * matching Bean property, should an exception be thrown (true), * or should JSON Property value be quietly skipped (false)? *

* Default setting is false, meaning that unmappable * JSON Object properties will simply be ignored. */ FAIL_ON_UNKNOWN_BEAN_PROPERTY(false), /* /********************************************************************** /* Write-related features that do not affect caching /********************************************************************** */ /** * Feature that defines what to do with {@link java.util.Map} entries and Java Bean * properties that have null as value: if enabled, they will be written out normally; * if disabled, such entries and properties will be ignored. *

* Default setting is false so that any null-valued properties * are ignored during serialization. */ WRITE_NULL_PROPERTIES(false), /** * Feature that determines whether Enum values are written using * numeric index (true), or String representation from calling * {@link Enum#toString()} (false). *

* Feature is disabled by default, * so that Enums are serialized as JSON Strings. */ WRITE_ENUMS_USING_INDEX(false), /** * Feature that determines whether Date (and date/time) values * (and Date-based things like {@link java.util.Calendar}s) are to be * serialized as numeric timestamps (true), * or using a textual representation (false) *

* Feature is disabled by default, so that date/time values are * serialized as text, NOT timestamp. * * @since 2.7 */ WRITE_DATES_AS_TIMESTAMP(false), /** * Feature that can be enabled to use "pretty-printing", basic indentation * to make resulting JSON easier to read by humans by adding white space * such as line feeds and indentation. *

* Default setting is false so that no pretty-printing is done * (unless explicitly constructed with a pretty printer object) */ PRETTY_PRINT_OUTPUT(false), /** * Feature that determines whether JsonGenerator.flush() is * called after write() method that takes JsonGenerator * as an argument completes (that is, does NOT affect methods * that use other destinations). * This usually makes sense; but there are cases where flushing * should not be forced: for example when underlying stream is * compressing and flush() causes compression state to be flushed * (which occurs with some compression codecs). *

* Feature is enabled by default. */ FLUSH_AFTER_WRITE_VALUE(true), /** * Feature that determines what happens when we encounter a value of * unrecognized type for which we do not have standard handler: if enabled, * will throw a {@link JSONObjectException}, if disabled simply * calls {@link Object#toString} and uses that JSON String as serialization. *

* NOTE: if {@link #HANDLE_JAVA_BEANS} is enabled, this setting typically * has no effect, since otherwise unknown types are recognized as * Bean types. * *

* Feature is disabled by default * so that no exceptions are thrown. */ FAIL_ON_UNKNOWN_TYPE_WRITE(false), /* /********************************************************************** /* Features that affect introspection /********************************************************************** */ /** * Feature that determines whether Bean types (Java objects with * getters and setters that expose state to serialize) will be * recognized and handled or not. * When enabled, any types that are not recognized as standard JDK * data structures, primitives or wrapper values will be introspected * and handled as Java Beans (can be read/written as long as JSON * matches properties discovered); when disabled, they may only be serialized * (using {@link Object#toString} method), and can not be deserialized. *

* Feature is enabled by default, but can be disabled do avoid use * of Bean reflection for cases where it is not desired. */ HANDLE_JAVA_BEANS(true, true), /** * Feature that determines whether "read-only" properties of Beans * (properties that only have a getter but no matching setter) are * to be included in Bean serialization or not; if disabled, * only properties have have both setter and getter are serialized. * Note that feature is only used if {@link #HANDLE_JAVA_BEANS} * is also enabled. *

* Feature is enabled by default, * so that all Bean properties are serialized. */ WRITE_READONLY_BEAN_PROPERTIES(true, true), /** * Feature that determines whether access to {@link java.lang.reflect.Method}s and * {@link java.lang.reflect.Constructor}s that are used with dynamically * introspected Beans may be forced using * {@link java.lang.reflect.AccessibleObject#setAccessible} or not. *

* Feature is enabled by default, so that access may be forced. */ FORCE_REFLECTION_ACCESS(true, true), /** * Whether "is-getters" (like public boolean isValuable()) are detected * for use or not. Note that in addition to naming, and lack of arguments, return * value also has to be boolean or java.lang.Boolean. * * @since 2.5 */ USE_IS_GETTERS(true, true), /** * Feature that enables use of public fields instead of setters and getters, * in cases where no setter/getter is available. *

* Feature is disabled by default (for backwards compatibility), so fields * are not used unless explicitly enabled. * * @since 2.8 */ USE_FIELDS(false, true), ; /* /********************************************************************** /* Enum impl /********************************************************************** */ private final boolean _defaultState; /** * Flag for features that affect caching of readers, writers, * and changing of which needs to result in flushing. * * @since 2.8 */ private final boolean _affectsCaching; private final int _mask; private Feature(boolean defaultState) { this(defaultState, false); } private Feature(boolean defaultState, boolean affectsCaching) { _defaultState = defaultState; _affectsCaching = affectsCaching; _mask = (1 << ordinal()); } public static int defaults() { int flags = 0; for (Feature value : values()) { if (value.enabledByDefault()) { flags |= value.mask(); } } return flags; } /** * Method for calculating bitset of features that force flushing of * POJO handler caches. * * @since 2.8 */ public static int cacheBreakers() { int flags = 0; for (Feature value : values()) { if (value.affectsCaching()) { flags |= value.mask(); } } return flags; } public final boolean enabledByDefault() { return _defaultState; } public final boolean affectsCaching() { return _affectsCaching; } public final int mask() { return _mask; } public final boolean isDisabled(int flags) { return (flags & _mask) == 0; } public final boolean isEnabled(int flags) { return (flags & _mask) != 0; } } // Important: has to come before 'std' instance, since it refers to it private final static int DEFAULT_FEATURES = Feature.defaults(); /** * Singleton instance with standard, default configuration. * May be used with direct references like: *

     *   String json = JSON.std.asString(map);
     *
*/ public final static JSON std = new JSON(); /* /********************************************************************** /* Configuration, helper objects /********************************************************************** */ /** * Underlying JSON factory used for creating Streaming parsers and * generators. */ protected final JsonFactory _jsonFactory; /** * Optional handler for {@link TreeNode} values: if defined, we can * read and write {@link TreeNode} instances that codec supports. */ protected final TreeCodec _treeCodec; /** * Blueprint instance of the reader to use for reading JSON as simple * Objects. */ protected final JSONReader _reader; /** * Blueprint isntance of the writer to use for writing JSON given * simple Objects. */ protected final JSONWriter _writer; /* /********************************************************************** /* Configuration, simple settings /********************************************************************** */ protected final int _features; protected final PrettyPrinter _prettyPrinter; /* /********************************************************************** /* Basic construction /********************************************************************** */ public JSON() { this(DEFAULT_FEATURES, new JsonFactory(), null); } protected JSON(int features, JsonFactory jsonF, TreeCodec trees) { this(features, jsonF, trees, null, null, // reader, writer null); } protected JSON(int features, JsonFactory jsonF, TreeCodec trees, JSONReader r, JSONWriter w, PrettyPrinter pp) { _features = features; _jsonFactory = jsonF; _treeCodec = trees; TypeDetector td = _defaultTypeDetector(features); _reader = (r == null) ? _defaultReader(features, trees, td) : r; _writer = (w == null) ? _defaultWriter(features, trees, td) : w; _prettyPrinter = pp; } protected TypeDetector _defaultTypeDetector(int features) { return TypeDetector.blueprint(features); } protected JSONReader _defaultReader(int features, TreeCodec tc, TypeDetector td) { return new JSONReader(features, td, tc, CollectionBuilder.defaultImpl(), MapBuilder.defaultImpl()); } protected JSONWriter _defaultWriter(int features, TreeCodec tc, TypeDetector td) { return new JSONWriter(features, td, tc); } /* /********************************************************************** /* Adapting /********************************************************************** */ /** * Convenience method for constructing an adapter that uses this * instance as a {@link ObjectCodec} */ public ObjectCodec asCodec() { return new JSONAsObjectCodec(this); } /* /********************************************************************** /* Versioned /********************************************************************** */ @Override public Version version() { return PackageVersion.VERSION; } /* /********************************************************************** /* Mutant factories /********************************************************************** */ public JSON with(JsonFactory f) { if (f == _jsonFactory) { return this; } return _with(_features, f, _treeCodec, _reader, _writer, _prettyPrinter); } /** * Mutant factory for constructing an instance with specified {@link TreeCodec}, * and returning new instance (or, if there would be no change, this instance). */ public JSON with(TreeCodec c) { if (c == _treeCodec) { return this; } return _with(_features, _jsonFactory, c, _reader, _writer.with(c), _prettyPrinter); } /** * Mutant factory for constructing an instance with specified {@link JSONReader}, * and returning new instance (or, if there would be no change, this instance). */ public JSON with(JSONReader r) { if (r == _reader) { return this; } return _with(_features, _jsonFactory, _treeCodec, r, _writer, _prettyPrinter); } /** * Mutant factory for constructing an instance with specified {@link JSONWriter}, * and returning new instance (or, if there would be no change, this instance). */ public JSON with(JSONWriter w) { if (w == _writer) { return this; } return _with( _features, _jsonFactory, _treeCodec, _reader, w, _prettyPrinter); } /** * Mutant factory for constructing an instance with specified {@link PrettyPrinter}, * and returning new instance (or, if there would be no change, this instance). */ public JSON with(PrettyPrinter pp) { if (_prettyPrinter == pp) { return this; } return _with(_features, _jsonFactory, _treeCodec, _reader, _writer, pp); } /** * Mutant factory for constructing an instance with specified {@link MapBuilder}, * and returning new instance (or, if there would be no change, this instance). */ public JSON with(MapBuilder b) { JSONReader r = _reader.with(b); if (r == _reader) { return this; } return _with(_features, _jsonFactory, _treeCodec, r, _writer, _prettyPrinter); } /** * Mutant factory for constructing an instance with specified {@link CollectionBuilder}, * and returning new instance (or, if there would be no change, this instance). */ public JSON with(CollectionBuilder b) { JSONReader r = _reader.with(b); if (r == _reader) { return this; } return _with(_features, _jsonFactory, _treeCodec, r, _writer, _prettyPrinter); } /** * Mutant factory for constructing an instance with specified feature * enabled or disabled (depending on state), and returning * an instance with that setting; this may either be this instance (if feature * already had specified state), or a newly constructed instance. */ public JSON with(Feature feature, boolean state) { int f = _features; if (state) { f |= feature.mask(); } else { f &= ~feature.mask(); } return _with(f); } /** * Mutant factory for constructing an instance with specified features * enabled. */ public JSON with(Feature ... features) { int flags = _features; for (Feature feature : features) { flags |= feature.mask(); } return _with(flags); } /** * Mutant factory for constructing an instance with specified features * disabled. */ public JSON without(Feature ... features) { int flags = _features; for (Feature feature : features) { flags &= ~feature.mask(); } return _with(flags); } /** * Internal mutant factory method used for constructing */ protected final JSON _with(int features) { if (_features == features) { return this; } return _with(features, _jsonFactory, _treeCodec, _reader, _writer, _prettyPrinter); } /* /********************************************************************** /* Methods sub-classes must override /********************************************************************** */ protected final JSON _with(int features, JsonFactory jsonF, TreeCodec trees, JSONReader reader, JSONWriter writer, PrettyPrinter pp) { if (getClass() != JSON.class) { throw new IllegalStateException("Sub-classes MUST override _with(...)"); } return new JSON(features, jsonF, trees, reader, writer, pp); } /* /********************************************************************** /* Simple accessors /********************************************************************** */ public TreeCodec getTreeCodec() { return _treeCodec; } public JsonFactory getStreamingFactory() { return _jsonFactory; } public final boolean isEnabled(Feature f) { return (f.mask() & _features) != 0; } /* /********************************************************************** /* API: writing Simple objects as JSON /********************************************************************** */ public String asString(Object value) throws IOException, JSONObjectException { SegmentedStringWriter sw = new SegmentedStringWriter(_jsonFactory._getBufferRecycler()); try { _writeAndClose(value, _jsonFactory.createGenerator(sw)); } catch (JsonProcessingException e) { throw e; } catch (IOException e) { // shouldn't really happen, but is declared as possibility so: throw JSONObjectException.fromUnexpectedIOE(e); } return sw.getAndClear(); } public byte[] asBytes(Object value) throws IOException, JSONObjectException { ByteArrayBuilder bb = new ByteArrayBuilder(_jsonFactory._getBufferRecycler()); try { _writeAndClose(value, _jsonFactory.createGenerator(bb, JsonEncoding.UTF8)); } catch (JsonProcessingException e) { throw e; } catch (IOException e) { // shouldn't really happen, but is declared as possibility so: throw JSONObjectException.fromUnexpectedIOE(e); } byte[] result = bb.toByteArray(); bb.release(); return result; } public void write(Object value, JsonGenerator gen) throws IOException, JSONObjectException { // NOTE: no call to _config(); assumed to be fully configured _writerForOperation(gen).writeValue(value); if (Feature.FLUSH_AFTER_WRITE_VALUE.isEnabled(_features)) { gen.flush(); } } public void write(Object value, OutputStream out) throws IOException, JSONObjectException { _writeAndClose(value, _jsonFactory.createGenerator(out)); } public void write(Object value, Writer w) throws IOException, JSONObjectException { _writeAndClose(value, _jsonFactory.createGenerator(w)); } public void write(Object value, File f) throws IOException, JSONObjectException { _writeAndClose(value, _jsonFactory.createGenerator(f, JsonEncoding.UTF8)); } /* /********************************************************************** /* API: writing using Composers /********************************************************************** */ public JSONComposer composeUsing(JsonGenerator gen) throws IOException, JSONObjectException { return JSONComposer.streamComposer(_features, gen, false); } public JSONComposer composeTo(OutputStream out) throws IOException, JSONObjectException { return JSONComposer.streamComposer(_features, _config(_jsonFactory.createGenerator(out)), true); } public JSONComposer composeTo(Writer w) throws IOException, JSONObjectException { return JSONComposer.streamComposer(_features, _config(_jsonFactory.createGenerator(w)), true); } public JSONComposer composeTo(File f) throws IOException, JSONObjectException { return JSONComposer.streamComposer(_features, _config(_jsonFactory.createGenerator(f, JsonEncoding.UTF8)), true); } public JSONComposer composeString() throws IOException, JSONObjectException { SegmentedStringWriter out = new SegmentedStringWriter(_jsonFactory._getBufferRecycler()); JsonGenerator gen = _config(_jsonFactory.createGenerator(out) .setCodec(asCodec())); return JSONComposer.stringComposer(_features, gen, out); } public JSONComposer composeBytes() throws IOException, JSONObjectException { ByteArrayBuilder out = new ByteArrayBuilder(_jsonFactory._getBufferRecycler()); JsonGenerator gen = _config(_jsonFactory.createGenerator(out) .setCodec(asCodec())); return JSONComposer.bytesComposer(_features, gen, out); } public CollectionComposer> composeList() { List list = new ArrayList(); return composeCollection(list); } public > CollectionComposer composeCollection(C collection) { return new CollectionComposer(collection); } public MapComposer composeMap() { return composeMap(new LinkedHashMap()); } public MapComposer composeMap(Map map) { return new MapComposer(map); } /* /********************************************************************** /* API: reading JSON as Simple Objects /********************************************************************** */ public List listFrom(Object source) throws IOException, JSONObjectException { if (source instanceof JsonParser) { // note: no call to _config(), should come pre-configured JsonParser p = _initForReading((JsonParser) source); List result = _readerForOperation(p).readList(); // Need to consume the token too p.clearCurrentToken(); return result; } JsonParser p = _parser(source); try { _initForReading(_config(p)); List result = _readerForOperation(p).readList(); JsonParser p0 = p; p = null; _close(p0, null); return result; } catch (Exception e) { return _closeWithError(p, e); } } public List listOfFrom(Class type, Object source) throws IOException, JSONObjectException { if (source instanceof JsonParser) { // note: no call to _config(), should come pre-configured JsonParser p = _initForReading((JsonParser) source); List result = _readerForOperation(p).readListOf(type); // Need to consume the token too p.clearCurrentToken(); return result; } JsonParser p = _parser(source); try { _initForReading(_config(p)); List result = _readerForOperation(p).readListOf(type); JsonParser p0 = p; p = null; _close(p0, null); return result; } catch (Exception e) { return _closeWithError(p, e); } } public Object[] arrayFrom(Object source) throws IOException, JSONObjectException { if (source instanceof JsonParser) { JsonParser p = _initForReading((JsonParser) source); Object[] result = _readerForOperation(p).readArray(); p.clearCurrentToken(); return result; } JsonParser p = _parser(source); try { _initForReading(_config(p)); Object[] result = _readerForOperation(p).readArray(); JsonParser p0 = p; p = null; _close(p0, null); return result; } catch (Exception e) { return _closeWithError(p, e); } } public T[] arrayOfFrom(Class type, Object source) throws IOException, JSONObjectException { if (source instanceof JsonParser) { JsonParser p = _initForReading((JsonParser) source); T[] result = _readerForOperation(p).readArrayOf(type); p.clearCurrentToken(); return result; } JsonParser p = _parser(source); try { _initForReading(_config(p)); T[] result = _readerForOperation(p).readArrayOf(type); JsonParser p0 = p; p = null; _close(p0, null); return result; } catch (Exception e) { return _closeWithError(p, e); } } @SuppressWarnings("unchecked") public Map mapFrom(Object source) throws IOException, JSONObjectException { if (source instanceof JsonParser) { JsonParser p = _initForReading((JsonParser) source); Map result = _readerForOperation(p).readMap(); p.clearCurrentToken(); return (Map) result; } JsonParser p = _parser(source); try { _initForReading(_config(p)); Map result = _readerForOperation(p).readMap(); JsonParser p0 = p; p = null; _close(p0, null); return (Map) result; } catch (Exception e) { return _closeWithError(p, e); } } public T beanFrom(Class type, Object source) throws IOException, JSONObjectException { if (source instanceof JsonParser) { JsonParser p = _initForReading((JsonParser) source); T result = _readerForOperation(p).readBean(type); p.clearCurrentToken(); return result; } JsonParser p = _parser(source); try { _initForReading(_config(p)); T result = _readerForOperation(p).readBean(type); JsonParser p0 = p; p = null; _close(p0, null); return result; } catch (Exception e) { return _closeWithError(p, e); } } /** * Read method that will take given JSON Source (of one of supported types), * read contents and map it to one of simple mappings ({@link java.util.Map} * for JSON Objects, {@link java.util.List} for JSON Arrays, {@link java.lang.String} * for JSON Strings, null for JSON null, {@link java.lang.Boolean} for JSON booleans * and {@link java.lang.Number} for JSON numbers. *

* Supported source types include: *

    *
  • {@link java.io.InputStream}
  • *
  • {@link java.io.Reader}
  • *
  • {@link java.io.File}
  • *
  • {@link java.net.URL}
  • *
  • {@link java.lang.String}
  • *
  • byte[]
  • *
  • char[]
  • *
*/ public Object anyFrom(Object source) throws IOException { if (source instanceof JsonParser) { JsonParser p = _initForReading((JsonParser) source); Object result = _readerForOperation(p).readValue(); p.clearCurrentToken(); return result; } JsonParser p = _parser(source); try { _initForReading(_config(p)); Object result = _readerForOperation(p).readValue(); JsonParser p0 = p; p = null; _close(p0, null); return result; } catch (Exception e) { _close(p, e); return null; } } /** * Method for reading content as a JSON Tree (of type that configured * {@link TreeCodec}, see {@link #with(TreeCodec)}) supports. * * @since 2.8 */ @SuppressWarnings("unchecked") public TreeNode treeFrom(Object source) throws IOException, JSONObjectException { if (_treeCodec == null) { _noTreeCodec("read TreeNode"); } if (source instanceof JsonParser) { JsonParser p = _initForReading((JsonParser) source); T result = (T) _treeCodec.readTree(p); p.clearCurrentToken(); return result; } JsonParser p = _parser(source); try { _initForReading(_config(p)); T result = (T) _treeCodec.readTree(p); JsonParser p0 = p; p = null; _close(p0, null); return result; } catch (Exception e) { _close(p, e); return null; } } /* /********************************************************************** /* API: TreeNode construction /********************************************************************** */ /** * Convenience method, equivalent to: *
     *   getTreeCodec().createArrayNode();
     *
* Note that for call to succeed a {@link TreeCodec} must have been * configured with this instance using {@link #with(TreeCodec)} method. * * @since 2.8 */ @SuppressWarnings("unchecked") public T createArrayNode() { if (_treeCodec == null) { _noTreeCodec("create Object node"); } return (T) _treeCodec.createArrayNode(); } /** * Convenience method, equivalent to: *
     *   getTreeCodec().createObjectNode();
     *
* Note that for call to succeed a {@link TreeCodec} must have been * configured with this instance using {@link #with(TreeCodec)} method. * * @since 2.8 */ @SuppressWarnings("unchecked") public T createObjectNode() { if (_treeCodec == null) { _noTreeCodec("create Object node"); } return (T) _treeCodec.createObjectNode(); } /* /********************************************************************** /* Internal methods, writing /********************************************************************** */ protected final void _writeAndClose(Object value, JsonGenerator g) throws IOException { boolean closed = false; try { _config(g); _writerForOperation(g).writeValue(value); closed = true; g.close(); } finally { if (!closed) { // need to catch possible failure, so as not to mask problem try { g.close(); } catch (IOException ioe) { } } } } protected JSONWriter _writerForOperation(JsonGenerator gen) { return _writer.perOperationInstance(_features, gen); } /* /********************************************************************** /* Internal methods, reading /********************************************************************** */ protected JSONReader _readerForOperation(JsonParser p) { return _reader.perOperationInstance(_features, p); } protected JsonParser _parser(Object source) throws IOException, JSONObjectException { final JsonFactory f = _jsonFactory; final Class type = source.getClass(); if (type == String.class) { return f.createParser((String) source); } if (type == byte[].class) { return f.createParser((byte[]) source); } if (source instanceof InputStream) { return f.createParser((InputStream) source); } if (source instanceof Reader) { return f.createParser((Reader) source); } if (source instanceof URL) { return f.createParser((URL) source); } if (type == char[].class) { return f.createParser(new CharArrayReader((char[]) source)); } if (source instanceof File) { return f.createParser((File) source); } if (source instanceof CharSequence) { return f.createParser(((CharSequence) source).toString()); } throw new JSONObjectException("Can not use Source of type "+source.getClass().getName() +" as input (use an InputStream, Reader, String, byte[], File or URL"); } protected JsonParser _initForReading(JsonParser p) throws IOException { /* First: must point to a token; if not pointing to one, advance. * This occurs before first read from JsonParser, as well as * after clearing of current token. */ JsonToken t = p.getCurrentToken(); if (t == null) { // and then we must get something... t = p.nextToken(); if (t == null) { // not cool is it? throw JSONObjectException.from(p, "No content to map due to end-of-input"); } } return p; } /* /********************************************************************** /* Internal methods, other /********************************************************************** */ protected JsonGenerator _config(JsonGenerator g) { // First, possible pretty printing PrettyPrinter pp = _prettyPrinter; if (pp != null) { if (pp instanceof Instantiatable) { pp = (PrettyPrinter) ((Instantiatable) pp).createInstance(); } g.setPrettyPrinter(pp); } else if (isEnabled(Feature.PRETTY_PRINT_OUTPUT)) { g.useDefaultPrettyPrinter(); } return g; } protected JsonParser _config(JsonParser p) { // nothing to do, yet return p; } protected void _close(Closeable cl) { try { cl.close(); } catch (IOException ioe) { } } protected void _close(Closeable cl, Exception e) throws IOException { if (cl != null) { if (e == null) { cl.close(); } else { try { cl.close(); } catch (Exception secondaryEx) { // what should we do here, if anything? } } } if (e != null) { if (e instanceof IOException) { throw (IOException) e; } if (e instanceof RuntimeException) { throw (RuntimeException) e; } throw new IOException(e); // should never occur } } /** * @since 2.8.2 */ protected T _closeWithError(Closeable cl, Exception e) throws IOException { if (cl != null) { try { cl.close(); } catch (Exception secondaryEx) { // what should we do here, if anything? } } if (e instanceof IOException) { throw (IOException) e; } if (e instanceof RuntimeException) { throw (RuntimeException) e; } throw new IOException(e); // should never occur } protected void _noTreeCodec(String msg) { throw new IllegalStateException("JSON instance does not have configured TreeCodec to "+msg); } } JSONComposer.java000066400000000000000000000113311323200335100340750ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/obpackage com.fasterxml.jackson.jr.ob; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.io.SegmentedStringWriter; import com.fasterxml.jackson.core.util.ByteArrayBuilder; import com.fasterxml.jackson.jr.ob.JSON.Feature; import com.fasterxml.jackson.jr.ob.comp.SequenceComposer; /** * Root-level composer object that acts as streaming "builder" * object, using an underlying {@link com.fasterxml.jackson.core.JsonGenerator} object. * This is similar to {@link com.fasterxml.jackson.jr.ob.comp.ArrayComposer}, but does not * have parent composer (so no end() method), * but does implement {@link java.io.Closeable} * * @param Type of result being composed. */ public class JSONComposer extends SequenceComposer> { protected final int _features; protected final boolean _closeGenerator; protected T _result; protected SegmentedStringWriter _stringWriter; protected ByteArrayBuilder _byteWriter; public JSONComposer(int features, JsonGenerator gen, boolean closeGenerator) { super(gen); _features = features; _stringWriter = null; _byteWriter = null; _closeGenerator = closeGenerator; } protected JSONComposer(int features, JsonGenerator gen, SegmentedStringWriter w) { super(gen); _features = features; _stringWriter = w; _byteWriter = null; _closeGenerator = true; } protected JSONComposer(int features, JsonGenerator gen, ByteArrayBuilder w) { super(gen); _features = features; _stringWriter = null; _byteWriter = w; _closeGenerator = true; } protected JSONComposer(int features, T result) { super(null); _features = features; _result = result; _stringWriter = null; _byteWriter = null; _closeGenerator = false; } /* /********************************************************************** /* API, factory methods /********************************************************************** */ public static JSONComposer streamComposer(int features, JsonGenerator gen, boolean closeGenerator) { return new JSONComposer(features, gen, closeGenerator); } public static JSONComposer stringComposer(int features, JsonGenerator gen, SegmentedStringWriter w) { return new JSONComposer(features, gen, w); } public static JSONComposer bytesComposer(int features, JsonGenerator gen, ByteArrayBuilder w) { return new JSONComposer(features, gen, w); } public static > JSONComposer collectionComposer(int features, T coll) { return new JSONComposer(features, coll); } public static JSONComposer> mapComposer(int features, Map map) { return new JSONComposer>(features, map); } /* /********************************************************************** /* API, life-cycle /********************************************************************** */ /** * Method to call to complete composition, flush any pending content, * and return instance of specified result type. */ @SuppressWarnings("unchecked") public T finish() throws IOException { if (_open) { _closeChild(); _open = false; if (_closeGenerator) { _generator.close(); } else if (Feature.FLUSH_AFTER_WRITE_VALUE.isEnabled(_features)) { _generator.flush(); } } if (_result == null) { Object x; if (_stringWriter != null) { x = _stringWriter.getAndClear(); _stringWriter = null; } else if (_byteWriter != null) { x = _byteWriter.toByteArray(); _byteWriter = null; } else { x = _generator.getOutputTarget(); } _result = (T) x; } return _result; } /* /********************************************************************** /* Abstract method impls /********************************************************************** */ @Override protected JSONComposer _start() throws IOException { // Should never be called throw _illegalCall(); } @Override protected Object _finish() throws IOException { // Should never be called throw _illegalCall(); } } JSONObjectException.java000066400000000000000000000265111323200335100354010ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/obpackage com.fasterxml.jackson.jr.ob; import java.io.IOException; import java.io.Serializable; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import com.fasterxml.jackson.core.JsonLocation; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; /** * Standard exception exposed by this package; equivalent of * com.fasterxml.jackson.databind.JsonMappingException * (and, in fact, much of implementation came from that class, but * had to be cut-n-pasted since we do not depend on databind package). */ public class JSONObjectException extends JsonProcessingException { private static final long serialVersionUID = 1L; /** * Let's limit length of reference chain, to limit damage in cases * of infinite recursion. */ final static int MAX_REFS_TO_LIST = 250; /* /********************************************************** /* Helper classes /********************************************************** */ /** * Simple bean class used to contain references. References * can be added to indicate execution/reference path that * lead to the problem that caused this exception to be * thrown. */ public static class Reference implements Serializable { private static final long serialVersionUID = 1L; /** * Object through which reference was resolved. Can be either * actual instance (usually the case for serialization), or * Class (usually the case for deserialization). */ protected Object _from; /** * Name of field (for beans) or key (for Maps) that is part * of the reference. May be null for Collection types (which * generally have {@link #_index} defined), or when resolving * Map classes without (yet) having an instance to operate on. */ protected String _fieldName; /** * Index within a {@link Collection} instance that contained * the reference; used if index is relevant and available. * If either not applicable, or not available, -1 is used to * denote "not known". */ protected int _index = -1; /** * Default constructor for deserialization/sub-classing purposes */ protected Reference() { } public Reference(Object from) { _from = from; } public Reference(Object from, String fieldName) { _from = from; if (fieldName == null) { throw new NullPointerException("Can not pass null fieldName"); } _fieldName = fieldName; } public Reference(Object from, int index) { _from = from; _index = index; } public void setFrom(Object o) { _from = o; } public void setFieldName(String n) { _fieldName = n; } public void setIndex(int ix) { _index = ix; } public Object getFrom() { return _from; } public String getFieldName() { return _fieldName; } public int getIndex() { return _index; } @Override public String toString() { StringBuilder sb = new StringBuilder(); Class cls = (_from instanceof Class) ? ((Class)_from) : _from.getClass(); /* Hmmh. Although Class.getName() is mostly ok, it does look * butt-ugly for arrays. So let's use getSimpleName() instead; * but have to prepend package name too. */ Package pkg = cls.getPackage(); if (pkg != null) { sb.append(pkg.getName()); sb.append('.'); } sb.append(cls.getSimpleName()); sb.append('['); if (_fieldName != null) { sb.append('"'); sb.append(_fieldName); sb.append('"'); } else if (_index >= 0) { sb.append(_index); } else { sb.append('?'); } sb.append(']'); return sb.toString(); } } /* /********************************************************** /* State/configuration /********************************************************** */ /** * Path through which problem that triggering throwing of * this exception was reached. */ protected LinkedList _path; /* /********************************************************** /* Life-cycle /********************************************************** */ public JSONObjectException(String msg) { super(msg); } public JSONObjectException(String msg, Throwable rootCause) { super(msg, rootCause); } public JSONObjectException(String msg, JsonLocation loc) { super(msg, loc); } public JSONObjectException(String msg, JsonLocation loc, Throwable rootCause) { super(msg, loc, rootCause); } public static JSONObjectException from(JsonParser p, String msg) { return new JSONObjectException(msg, ((p == null) ? null : p.getTokenLocation())); } public static JSONObjectException from(JsonParser p, String msg, Object... args) { if (args.length > 0) { msg = String.format(msg, args); } return new JSONObjectException(msg, ((p == null) ? null : p.getTokenLocation())); } public static JSONObjectException from(JsonParser p, Throwable problem, String msg, Object... args) { if (args.length > 0) { msg = String.format(msg, args); } return new JSONObjectException(msg, ((p == null) ? null : p.getTokenLocation()), problem); } /** * Factory method used when "upgrading" an {@link IOException} into * {@link JSONObjectException}: usually only needed to comply with * a signature. */ public static JSONObjectException fromUnexpectedIOE(IOException src) { return new JSONObjectException("Unexpected IOException (of type " +src.getClass().getName()+"): "+src.getMessage(), (JsonLocation)null, src); } /** * Method that can be called to either create a new JsonMappingException * (if underlying exception is not a JsonMappingException), or augment * given exception with given path/reference information. * * This version of method is called when the reference is through a * non-indexed object, such as a Map or POJO/bean. */ public static JSONObjectException wrapWithPath(Throwable src, Object refFrom, String refFieldName) { return wrapWithPath(src, new Reference(refFrom, refFieldName)); } /** * Method that can be called to either create a new JsonMappingException * (if underlying exception is not a JsonMappingException), or augment * given exception with given path/reference information. * * This version of method is called when the reference is through an * index, which happens with arrays and Collections. */ public static JSONObjectException wrapWithPath(Throwable src, Object refFrom, int index) { return wrapWithPath(src, new Reference(refFrom, index)); } /** * Method that can be called to either create a new JsonMappingException * (if underlying exception is not a JsonMappingException), or augment * given exception with given path/reference information. */ public static JSONObjectException wrapWithPath(Throwable src, Reference ref) { JSONObjectException jme; if (src instanceof JSONObjectException) { jme = (JSONObjectException) src; } else { String msg = src.getMessage(); if (msg == null || msg.length() == 0) { msg = "(was "+src.getClass().getName()+")"; } jme = new JSONObjectException(msg, null, src); } jme.prependPath(ref); return jme; } /* /********************************************************** /* Accessors/mutators /********************************************************** */ /** * Method for accessing full structural path within type hierarchy * down to problematic property. */ public List getPath() { if (_path == null) { return Collections.emptyList(); } return Collections.unmodifiableList(_path); } /** * Method for accesing description of path that lead to the * problem that triggered this exception */ public String getPathReference() { return getPathReference(new StringBuilder()).toString(); } public StringBuilder getPathReference(StringBuilder sb) { _appendPathDesc(sb); return sb; } /** * Method called to prepend a reference information in front of * current path */ public void prependPath(Object referrer, String fieldName) { Reference ref = new Reference(referrer, fieldName); prependPath(ref); } /** * Method called to prepend a reference information in front of * current path */ public void prependPath(Object referrer, int index) { Reference ref = new Reference(referrer, index); prependPath(ref); } public void prependPath(Reference r) { if (_path == null) { _path = new LinkedList(); } /* Also: let's not increase without bounds. Could choose either * head or tail; tail is easier (no need to ever remove), as * well as potentially more useful so let's use it: */ if (_path.size() < MAX_REFS_TO_LIST) { _path.addFirst(r); } } /* /********************************************************** /* Overridden methods /********************************************************** */ @Override public String getLocalizedMessage() { return _buildMessage(); } /** * Method is overridden so that we can properly inject description * of problem path, if such is defined. */ @Override public String getMessage() { return _buildMessage(); } protected String _buildMessage() { String msg = super.getMessage(); if (_path == null) { return msg; } StringBuilder sb = (msg == null) ? new StringBuilder() : new StringBuilder(msg); sb.append(" (through reference chain: "); sb = getPathReference(sb); sb.append(')'); return sb.toString(); } @Override public String toString() { return getClass().getName()+": "+getMessage(); } /* /********************************************************** /* Internal methods /********************************************************** */ protected void _appendPathDesc(StringBuilder sb) { if (_path == null) { return; } Iterator it = _path.iterator(); while (it.hasNext()) { sb.append(it.next().toString()); if (it.hasNext()) { sb.append("->"); } } } } PackageVersion.java.in000066400000000000000000000011071323200335100351220ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/obpackage @package@; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.core.Versioned; import com.fasterxml.jackson.core.util.VersionUtil; /** * Automatically generated from PackageVersion.java.in during * packageVersion-generate execution of maven-replacer-plugin in * pom.xml. */ public final class PackageVersion implements Versioned { public final static Version VERSION = VersionUtil.parseVersion( "@projectversion@", "@projectgroupid@", "@projectartifactid@"); @Override public Version version() { return VERSION; } } jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/comp/000077500000000000000000000000001323200335100317675ustar00rootroot00000000000000ArrayComposer.java000066400000000000000000000027351323200335100353500ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/comppackage com.fasterxml.jackson.jr.ob.comp; import java.io.IOException; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; public class ArrayComposer extends SequenceComposer> { protected final PARENT _parent; public ArrayComposer(PARENT parent, JsonGenerator g) { super(g); _parent = parent; } /* /********************************************************************** /* Abstract method impls /********************************************************************** */ @Override protected ArrayComposer _start() throws IOException, JsonProcessingException { _generator.writeStartArray(); return this; } @Override protected Object _finish() throws IOException, JsonProcessingException { if (_open) { _open = false; _generator.writeEndArray(); } return null; } /* /********************************************************************** /* Compose methods, structures /********************************************************************** */ public PARENT end() throws IOException, JsonProcessingException { _closeChild(); if (_open) { _open = false; _generator.writeEndArray(); _parent._childClosed(); } return _parent; } } CollectionComposer.java000066400000000000000000000121141323200335100363550ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/comppackage com.fasterxml.jackson.jr.ob.comp; import java.util.*; import com.fasterxml.jackson.core.JsonGenerator; public class CollectionComposer> extends ComposerBase { protected final PARENT _parent; protected C _collection; public CollectionComposer(PARENT parent) { super(); _parent = parent; } public CollectionComposer(C coll) { super(); _parent = null; _collection = coll; } public static > CollectionComposer rootComposer(T coll) { return new CollectionComposer(coll); } /* /********************************************************************** /* Abstract method impls /********************************************************************** */ @Override public void flush() { } @Override protected CollectionComposer _start() { if (_collection == null) { _collection = constructCollection(); } return this; } @Override protected C _finish() { if (_open) { _open = false; } return _collection; } /* /********************************************************************** /* Compose methods, structures /********************************************************************** */ public CollectionComposer,?> startArray() { _closeChild(); CollectionComposer,?> child = _startCollection(this); _collection.add(child._collection); return child; } public MapComposer> startObject() { _closeChild(); MapComposer> child = _startMap(this); _collection.add(child._map); return child; } public C finish() { return _finish(); } /* /********************************************************************** /* Compose methods, scalars, number /********************************************************************** */ public CollectionComposer add(int value) { _collection.add(Integer.valueOf(value)); return this; } public CollectionComposer add(long value) { _collection.add(Long.valueOf(value)); return this; } public CollectionComposer add(double value) { _collection.add(Double.valueOf(value)); return this; } /* /********************************************************************** /* Compose methods, scalars, textual / binary /********************************************************************** */ public CollectionComposer add(String value) { _collection.add(value); return this; } public CollectionComposer add(CharSequence value) { String str = (value == null) ? null : value.toString(); _collection.add(str); return this; } /* /********************************************************************** /* Compose methods, scalars, other /********************************************************************** */ public CollectionComposer addNull() { _collection.add(null); return this; } public CollectionComposer add(boolean value) { _collection.add(value ? Boolean.TRUE : Boolean.FALSE); return this; } /** * Method used to add Java Object ("POJO") into sequence being * composed: this requires that the underlying {@link JsonGenerator} * has a properly configured {@link com.fasterxml.jackson.core.ObjectCodec} * to use for serializer object. */ public CollectionComposer addObject(Object pojo) { _collection.add(pojo); return this; } /* /********************************************************************** /* Compose methods, structures /********************************************************************** */ public PARENT end() { _closeChild(); if (_open) { _open = false; _parent._childClosed(); } return _parent; } /* /********************************************************************** /* Overridable helper methods /********************************************************************** */ @SuppressWarnings("unchecked") protected C constructCollection() { return (C) new ArrayList(); } /* /********************************************************************** /* Internal helper methods /********************************************************************** */ protected void _closeChild() { if (_child != null) { Object value = _child._safeFinish(); _collection.add(value); _child = null; } } } ComposerBase.java000066400000000000000000000045671323200335100351510ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/comppackage com.fasterxml.jackson.jr.ob.comp; import java.io.Flushable; import java.io.IOException; import java.util.Collection; import com.fasterxml.jackson.core.JsonGenerator; /** * Base class for all composer implementations. */ public abstract class ComposerBase implements Flushable { protected ComposerBase _child; protected boolean _open = true; protected ComposerBase() { } /* /********************************************************************** /* Abstract methods sub-classes have to implement /********************************************************************** */ protected abstract ComposerBase _start() throws IOException; protected abstract Object _finish() throws IOException; /** * Helper method used to "peel away" bogus exception declaration */ protected Object _safeFinish() { try { return _finish(); } catch (IOException e) { throw new RuntimeException(e); } } protected final void _childClosed() { _child = null; } /* /********************************************************************** /* Helper methods for sub-classes /********************************************************************** */ protected IllegalStateException _illegalCall() { return new IllegalStateException("This code path should never be executed"); } protected

ArrayComposer

_startArray(P parent, JsonGenerator g) throws IOException { ArrayComposer

child = new ArrayComposer

(parent, g); _child = child; return child._start(); } protected

ObjectComposer

_startObject(P parent, JsonGenerator g) throws IOException { ObjectComposer

child = new ObjectComposer

(parent, g); _child = child; return child._start(); } protected

CollectionComposer _startCollection(P parent) { CollectionComposer child = new CollectionComposer>(parent); _child = child; return child._start(); } protected

MapComposer

_startMap(P parent) { MapComposer

child = new MapComposer

(parent); _child = child; return child._start(); } } MapComposer.java000066400000000000000000000111311323200335100347750ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/comppackage com.fasterxml.jackson.jr.ob.comp; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.SerializableString; public class MapComposer extends ComposerBase { protected final PARENT _parent; protected String _fieldName; protected Map _map; public MapComposer(PARENT parent) { super(); _parent = parent; } public MapComposer(Map map) { super(); _parent = null; _map = map; } @SuppressWarnings({ "unchecked", "rawtypes" }) public static MapComposer rootComposer(Map map) { return new MapComposer(map); } /* /********************************************************************** /* Abstract method impls /********************************************************************** */ @Override public void flush() throws IOException { } @Override protected MapComposer _start() { if (_map == null) { _map = constructMap(); } return this; } @Override protected Map _finish() { if (_open) { _open = false; } return _map; } /* /********************************************************************** /* Compose methods, structures /********************************************************************** */ public CollectionComposer,?> startArrayField(String fieldName) { _closeChild(); _fieldName = fieldName; CollectionComposer,?> child = _startCollection(this); _map.put(fieldName, child._collection); return child; } public CollectionComposer,?> startArrayField(SerializableString fieldName) { return startArrayField(fieldName.getValue()); } public MapComposer> startObjectField(String fieldName) { _closeChild(); _fieldName = fieldName; MapComposer> child = _startMap(this); _map.put(fieldName, child._map); return child; } public MapComposer> startObjectField(SerializableString fieldName) { return startObjectField(fieldName.getValue()); } public PARENT end() { _closeChild(); if (_open) { _open = false; _parent._childClosed(); } return _parent; } public Map finish() { return _finish(); } /* /********************************************************************** /* Compose methods, scalars /********************************************************************** */ public MapComposer put(String fieldName, boolean value) { _map.put(fieldName, value ? Boolean.TRUE : Boolean.FALSE); return this; } public MapComposer putNull(String fieldName) { // could maybe just omit but... _map.put(fieldName, null); return this; } public MapComposer put(String fieldName, int value) { _map.put(fieldName, value); return this; } public MapComposer put(String fieldName, long value) { _map.put(fieldName, value); return this; } public MapComposer put(String fieldName, double value) { _map.put(fieldName, value); return this; } public MapComposer put(String fieldName, String value) { _map.put(fieldName, value); return this; } public MapComposer put(String fieldName, CharSequence value) { String str = (value == null) ? null : value.toString(); _map.put(fieldName, str); return this; } /* /********************************************************************** /* Overridable helper methods /********************************************************************** */ protected Map constructMap() { return new LinkedHashMap(); } /* /********************************************************************** /* Internal methods /********************************************************************** */ protected void _closeChild() { if (_child != null) { Object value = _child._safeFinish(); _map.put(_fieldName, value); _child = null; } } } ObjectComposer.java000066400000000000000000000125631323200335100355000ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/comppackage com.fasterxml.jackson.jr.ob.comp; import java.io.IOException; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.SerializableString; public class ObjectComposer extends ComposerBase { protected final PARENT _parent; protected final JsonGenerator _generator; public ObjectComposer(PARENT parent, JsonGenerator g) { super(); _parent = parent; _generator = g; } /* /********************************************************************** /* Abstract method impls /********************************************************************** */ @Override public void flush() throws IOException { if (_generator != null) { _generator.close(); } } @Override protected ObjectComposer _start() throws IOException, JsonProcessingException { _generator.writeStartObject(); return this; } @Override protected Object _finish() throws IOException, JsonProcessingException { if (_open) { _open = false; _generator.writeEndObject(); } return null; } /* /********************************************************************** /* Compose methods, structures /********************************************************************** */ public ArrayComposer> startArrayField(String fieldName) throws IOException, JsonProcessingException { _closeChild(); _generator.writeFieldName(fieldName); return _startArray(this, _generator); } public ArrayComposer> startArrayField(SerializableString fieldName) throws IOException, JsonProcessingException { _closeChild(); _generator.writeFieldName(fieldName); return _startArray(this, _generator); } public ObjectComposer> startObjectField(String fieldName) throws IOException, JsonProcessingException { _closeChild(); _generator.writeFieldName(fieldName); return _startObject(this, _generator); } public ObjectComposer> startObjectField(SerializableString fieldName) throws IOException, JsonProcessingException { _closeChild(); _generator.writeFieldName(fieldName); return _startObject(this, _generator); } public PARENT end() throws IOException, JsonProcessingException { _closeChild(); if (_open) { _open = false; _generator.writeEndObject(); _parent._childClosed(); } return _parent; } /* /********************************************************************** /* Compose methods, scalars /********************************************************************** */ public ObjectComposer put(String fieldName, boolean value) throws IOException, JsonProcessingException { _generator.writeBooleanField(fieldName, value); return this; } public ObjectComposer putNull(String fieldName) throws IOException, JsonProcessingException { _generator.writeNullField(fieldName); return this; } /** * Method used to put a Java Object ("POJO") value into Object being * composed: this requires that the underlying {@link JsonGenerator} * has a properly configured {@link com.fasterxml.jackson.core.ObjectCodec} * to use for serializer object. * * @since 2.6 */ public ObjectComposer putObject(String fieldName, Object value) throws IOException, JsonProcessingException { _generator.writeObjectField(fieldName, value); return this; } public ObjectComposer put(String fieldName, int value) throws IOException, JsonProcessingException { _generator.writeNumberField(fieldName, value); return this; } public ObjectComposer put(String fieldName, long value) throws IOException, JsonProcessingException { _generator.writeNumberField(fieldName, value); return this; } public ObjectComposer put(String fieldName, double value) throws IOException, JsonProcessingException { _generator.writeNumberField(fieldName, value); return this; } public ObjectComposer put(String fieldName, String value) throws IOException, JsonProcessingException { _generator.writeStringField(fieldName, value); return this; } public ObjectComposer put(String fieldName, CharSequence value) throws IOException, JsonProcessingException { String str = (value == null) ? null : value.toString(); _generator.writeStringField(fieldName, str); return this; } /* /********************************************************************** /* Internal methods /********************************************************************** */ protected void _closeChild() throws IOException, JsonProcessingException { if (_child != null) { _child._finish(); _child = null; } } } SequenceComposer.java000066400000000000000000000073241323200335100360410ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/comppackage com.fasterxml.jackson.jr.ob.comp; import java.io.IOException; import com.fasterxml.jackson.core.JsonGenerator; public abstract class SequenceComposer> extends ComposerBase { protected final JsonGenerator _generator; public SequenceComposer(JsonGenerator g) { super(); _generator = g; } /* /********************************************************************** /* Abstract methods from base class /********************************************************************** */ /** * Calls {@link JsonGenerator#flush} on underlying {@link JsonGenerator}. */ @Override public void flush() throws IOException { if (_generator != null) { _generator.close(); } } /* /********************************************************************** /* Compose methods, structures /********************************************************************** */ public ArrayComposer startArray() throws IOException { _closeChild(); return _startArray(_this(), _generator); } public ObjectComposer startObject() throws IOException { _closeChild(); return _startObject(_this(), _generator); } /* /********************************************************************** /* Compose methods, scalars, number /********************************************************************** */ public THIS add(int value) throws IOException { _generator.writeNumber(value); return _this(); } public THIS add(long value) throws IOException { _generator.writeNumber(value); return _this(); } public THIS add(double value) throws IOException { _generator.writeNumber(value); return _this(); } /* /********************************************************************** /* Compose methods, scalars, textual / binary /********************************************************************** */ public THIS add(String value) throws IOException { _generator.writeString(value); return _this(); } public THIS add(CharSequence value) throws IOException { String str = (value == null) ? null : value.toString(); _generator.writeString(str); return _this(); } /* /********************************************************************** /* Compose methods, scalars, other /********************************************************************** */ public THIS addNull() throws IOException { _generator.writeNull(); return _this(); } public THIS add(boolean value) throws IOException { _generator.writeBoolean(value); return _this(); } /** * Method used to add Java Object ("POJO") into sequence being * composed: this requires that the underlying {@link JsonGenerator} * has a properly configure {@link com.fasterxml.jackson.core.ObjectCodec} * to use for serializer object. */ public THIS addObject(Object pojo) throws IOException { _generator.writeObject(pojo); return _this(); } /* /********************************************************************** /* Internal helper methods /********************************************************************** */ protected void _closeChild() throws IOException { if (_child != null) { _child._finish(); _child = null; } } @SuppressWarnings("unchecked") protected THIS _this() { return (THIS) this; } } jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/000077500000000000000000000000001323200335100317725ustar00rootroot00000000000000AnyReader.java000066400000000000000000000147361323200335100344430ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import static com.fasterxml.jackson.core.JsonTokenId.*; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.core.JsonParser.NumberType; import com.fasterxml.jackson.jr.ob.*; /** * {@link ValueReader} used for "untyped" values; ones that are bound * to whatever {@link java.lang.Object} is the natural mapping to JSON * value that parser currently points to */ public class AnyReader extends ValueReader { public final static AnyReader std = new AnyReader(); @Override public Object readNext(JSONReader r, JsonParser p) throws IOException { p.nextToken(); return read(r, p); } @Override public Object read(JSONReader r, JsonParser p) throws IOException { JsonToken t = p.getCurrentToken(); int id = (t == null) ? ID_NO_TOKEN : t.id(); switch (id) { case ID_NULL: return null; case ID_START_OBJECT: return readFromObject(r, p, r._mapBuilder); case ID_START_ARRAY: if (r.arraysAsLists()) { return readCollectionFromArray(r, p, r._collectionBuilder); } return readArrayFromArray(r, p, r._collectionBuilder); case ID_STRING: return fromString(p.getText()); case ID_NUMBER_INT: { NumberType n = p.getNumberType(); if (n == NumberType.INT) { return Integer.valueOf(p.getIntValue()); } if (n == NumberType.LONG) { return Long.valueOf(p.getLongValue()); } return p.getBigIntegerValue(); } case ID_NUMBER_FLOAT: if (!JSON.Feature.USE_BIG_DECIMAL_FOR_FLOATS.isEnabled(r._features)) { NumberType n = p.getNumberType(); if (n == NumberType.FLOAT) { return Float.valueOf(p.getFloatValue()); } if (n == NumberType.DOUBLE) { return Double.valueOf(p.getDoubleValue()); } } return p.getDecimalValue(); case ID_TRUE: return fromBoolean(true); case ID_FALSE: return fromBoolean(false); case ID_EMBEDDED_OBJECT: return fromEmbedded(p.getEmbeddedObject()); // Others are error cases... /* default: case END_ARRAY: case END_OBJECT: case FIELD_NAME: case NOT_AVAILABLE: */ } throw JSONObjectException.from(p, "Unexpected value token: "+_tokenDesc(p)); } public Map readFromObject(JSONReader r, JsonParser p, MapBuilder b) throws IOException { // First, a minor optimization for empty Maps if (p.nextValue() == JsonToken.END_OBJECT) { return b.emptyMap(); } // and another for singletons... Object key = fromKey(p.getCurrentName()); Object value = read(r, p); if (p.nextValue() == JsonToken.END_OBJECT) { return b.singletonMap(key, value); } // but then it's loop-de-loop try { b = b.start().put(key, value); do { b = b.put(fromKey(p.getCurrentName()), read(r, p)); } while (p.nextValue() != JsonToken.END_OBJECT); } catch (IllegalArgumentException e) { throw JSONObjectException.from(p, e.getMessage()); } return b.build(); } public Object[] readArrayFromArray(JSONReader r, JsonParser p, CollectionBuilder b) throws IOException { // First two special cases; empty, single-element if (p.nextToken() == JsonToken.END_ARRAY) { return b.emptyArray(); } Object value = read(r, p); if (p.nextToken() == JsonToken.END_ARRAY) { return b.singletonArray(value); } try { b = b.start().add(value); do { b = b.add(read(r, p)); } while (p.nextToken() != JsonToken.END_ARRAY); return b.buildArray(); } catch (IllegalArgumentException e) { throw JSONObjectException.from(p, e.getMessage()); } } public Collection readCollectionFromArray(JSONReader r, JsonParser p, CollectionBuilder b) throws IOException { if (p.nextToken() == JsonToken.END_ARRAY) { return b.emptyCollection(); } Object value = read(r, p); if (p.nextToken() == JsonToken.END_ARRAY) { return b.singletonCollection(value); } try { b = b.start().add(value); do { b = b.add(read(r, p)); } while (p.nextToken() != JsonToken.END_ARRAY); return b.buildCollection(); } catch (IllegalArgumentException e) { throw JSONObjectException.from(p, e.getMessage()); } } /* /********************************************************************** /* Internal methods, simple scalar conversions /********************************************************************** */ /** * Method called to let implementation change a null value that has been * read from input. * Default implementation returns null as is. */ protected Object fromNull() throws IOException { return null; } /** * Method called to let implementation change a {@link java.lang.Boolean} value that has been * read from input. * Default implementation returns Boolean value as is. */ protected Object fromBoolean(boolean b) throws IOException { return b ? Boolean.TRUE : Boolean.FALSE; } /** * Method called to let implementation change a key of an Object field * after being parsed from input. * Default implementation returns key as is. */ protected Object fromKey(String key) throws IOException { return key; } /** * Method called to let implementation change a {@link java.lang.String} value that has been * read from input. * Default implementation returns String value as is. */ protected Object fromString(String str) throws IOException { // Nothing fancy, by default; return as is return str; } protected Object fromEmbedded(Object value) throws IOException { return value; } } ArrayReader.java000066400000000000000000000037121323200335100347620ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import java.io.IOException; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.jr.ob.JSONObjectException; /** * Reader for typed Array values. */ public class ArrayReader extends ValueReader { protected final Class _elementType; protected final ValueReader _valueReader; public ArrayReader(Class t, ValueReader vr) { _elementType = t; _valueReader = vr; } @Override public Object readNext(JSONReader r, JsonParser p) throws IOException { if (p.nextToken() != JsonToken.START_ARRAY) { if (p.hasToken(JsonToken.VALUE_NULL)) { return null; } return JSONObjectException.from(p, "Unexpected token "+p.getCurrentToken()+"; should get START_ARRAY"); } CollectionBuilder b = r._collectionBuilder(null); if (p.nextToken() == JsonToken.END_ARRAY) { return b.emptyArray(_elementType); } Object value = _valueReader.read(r, p); if (p.nextToken() == JsonToken.END_ARRAY) { return b.singletonArray(_elementType, value); } b = b.start().add(value); do { b = b.add(_valueReader.read(r, p)); } while (p.nextToken() != JsonToken.END_ARRAY); return b.buildArray(_elementType); } @Override public Object read(JSONReader r, JsonParser p) throws IOException { CollectionBuilder b = r._collectionBuilder(null); if (p.nextToken() == JsonToken.END_ARRAY) { return b.emptyArray(_elementType); } Object value = _valueReader.read(r, p); if (p.nextToken() == JsonToken.END_ARRAY) { return b.singletonArray(_elementType, value); } b = b.start().add(value); do { b = b.add(_valueReader.read(r, p)); } while (p.nextToken() != JsonToken.END_ARRAY); return b.buildArray(_elementType); } }BeanPropertyReader.java000066400000000000000000000051771323200335100363250ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; import com.fasterxml.jackson.jr.ob.JSONObjectException; /** * @since 2.8 (formerly part of `BeanDefinition`) */ public final class BeanPropertyReader { private final String _name; /** * For non-trivial non-bean types */ private final ValueReader _valueReader; /** * Setter method to use, if any; null if none */ private final Method _setter; /** * Field to assign value to, if no setter method defined; null if none */ private final Field _field; public BeanPropertyReader(String name, Field f, Method setter) { if ((f == null) && (setter == null)) { throw new IllegalArgumentException("Both `field` and `setter` can not be null"); } _name = name; _field = f; _setter = setter; _valueReader = null; } protected BeanPropertyReader(BeanPropertyReader src, ValueReader vr) { _name = src._name; _field = src._field; _setter = src._setter; _valueReader = vr; } public BeanPropertyReader withReader(ValueReader vr) { return new BeanPropertyReader(this, vr); } public Type genericSetterType() { if (_setter != null) { return _setter.getGenericParameterTypes()[0]; } return _field.getGenericType(); } public Class rawSetterType() { if (_setter != null) { return _setter.getParameterTypes()[0]; } return _field.getType(); } public ValueReader getReader() { return _valueReader; } public String getName() { return _name; } public void setValueFor(Object bean, Object value) throws IOException { try { if (_setter == null) { _field.set(bean, value); } else { _setter.invoke(bean, value); } } catch (Exception e) { Throwable t = e; if (t instanceof InvocationTargetException) { t = t.getCause(); } throw new JSONObjectException("Failed to set property '"+_name+"'; exception "+e.getClass().getName()+"): " +t.getMessage(), t); } } protected String _bean() { if (_setter != null) { return _setter.getDeclaringClass().getName(); } return _field.getDeclaringClass().getName(); } @Override public String toString() { return _name; } } BeanPropertyWriter.java000066400000000000000000000030261323200335100363660ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; import com.fasterxml.jackson.core.io.SerializedString; import com.fasterxml.jackson.jr.ob.JSONObjectException; /** * Simple container class used to contain information needed for serializing * value of a single POJO property. * * @since 2.8 */ public final class BeanPropertyWriter { public final SerializedString name; public final int typeId; private final Method _getter; private final Field _field; public BeanPropertyWriter(int typeId, String n, Field f, Method getter) { this.typeId = typeId; name = new SerializedString(n); _field = f; if ((getter == null) && (f == null)) { throw new IllegalArgumentException("Missing getter and field"); } _getter = getter; } public Object getValueFor(Object bean) throws IOException { try { if (_getter == null) { return _field.get(bean); } return _getter.invoke(bean); } catch (Exception e) { throw new JSONObjectException(String.format( "Failed to access property '%s'; exception (%s): %s", name, e.getClass().getName(), e.getMessage()), e); } } protected String _bean() { if (_getter == null) { return _field.getDeclaringClass().getName(); } return _getter.getDeclaringClass().getName(); } } BeanReader.java000066400000000000000000000145621323200335100345560ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import java.io.IOException; import java.lang.reflect.Constructor; import java.util.Map; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.jr.ob.JSON; import com.fasterxml.jackson.jr.ob.JSONObjectException; /** * Class that contains information about dynamically introspected * Bean types, to be able to deserialize (read) JSON into a POJO * and serialize (write) POJO as JSON. */ public class BeanReader extends ValueReader // so we can chain calls for Collections, arrays { protected final Class _type; protected final Map _propsByName; // for deserialization protected final Constructor _defaultCtor; protected final Constructor _stringCtor; protected final Constructor _longCtor; /** * Constructors used for deserialization use case */ public BeanReader(Class type, Map props, Constructor defaultCtor, Constructor stringCtor, Constructor longCtor) { _type = type; _propsByName = props; _defaultCtor = defaultCtor; _stringCtor = stringCtor; _longCtor = longCtor; } public Map propertiesByName() { return _propsByName; } public BeanPropertyReader findProperty(String name) { return _propsByName.get(name); } @Override public Object readNext(JSONReader r, JsonParser p) throws IOException { JsonToken t = p.nextToken(); try { switch (t) { case VALUE_NULL: return null; case VALUE_STRING: return create(p.getText()); case VALUE_NUMBER_INT: return create(p.getLongValue()); case START_OBJECT: { Object bean = create(); String propName; for (; (propName = p.nextFieldName()) != null; ) { BeanPropertyReader prop = findProperty(propName); if (prop == null) { handleUnknown(r, p, propName); continue; } ValueReader vr = prop.getReader(); prop.setValueFor(bean, vr.readNext(r, p)); } // also verify we are not confused... if (!p.hasToken(JsonToken.END_OBJECT)) { throw _reportProblem(p); } return bean; } default: } } catch (IOException e) { throw e; } catch (Exception e) { throw JSONObjectException.from(p, "Failed to create an instance of " +_type.getName()+" due to ("+e.getClass().getName()+"): "+e.getMessage(), e); } throw JSONObjectException.from(p, "Can not create a "+_type.getName()+" instance out of "+_tokenDesc(p)); } /** * Method used for deserialization; will read an instance of the bean * type using given parser. */ @Override public Object read(JSONReader r, JsonParser p) throws IOException { JsonToken t = p.getCurrentToken(); try { switch (t) { case VALUE_NULL: return null; case VALUE_STRING: return create(p.getText()); case VALUE_NUMBER_INT: return create(p.getLongValue()); case START_OBJECT: { Object bean = create(); String propName; for (; (propName = p.nextFieldName()) != null; ) { BeanPropertyReader prop = findProperty(propName); if (prop == null) { handleUnknown(r, p, propName); continue; } ValueReader vr = prop.getReader(); prop.setValueFor(bean, vr.readNext(r, p)); } // also verify we are not confused... if (!p.hasToken(JsonToken.END_OBJECT)) { throw _reportProblem(p); } return bean; } default: } } catch (IOException e) { throw e; } catch (Exception e) { throw JSONObjectException.from(p, e, "Failed to create an instance of %s due to (%s): %s", _type.getName(), e.getClass().getName(), e.getMessage()); } throw JSONObjectException.from(p, "Can not create a %s instance out of %s", _type.getName(), _tokenDesc(p)); } protected Object create() throws Exception { if (_defaultCtor == null) { throw new IllegalStateException("Class "+_type.getName()+" does not have default constructor to use"); } return _defaultCtor.newInstance(); } protected Object create(String str) throws Exception { if (_stringCtor == null) { throw new IllegalStateException("Class "+_type.getName()+" does not have single-String constructor to use"); } return _stringCtor.newInstance(str); } protected Object create(long l) throws Exception { if (_longCtor == null) { throw new IllegalStateException("Class "+_type.getName()+" does not have single-long constructor to use"); } return _longCtor.newInstance(l); } protected void handleUnknown(JSONReader reader, JsonParser parser, String fieldName) throws IOException { if (JSON.Feature.FAIL_ON_UNKNOWN_BEAN_PROPERTY.isEnabled(reader._features)) { throw JSONObjectException.from(parser, "Unrecognized JSON property '" +fieldName+"' for Bean type "+_type.getName()); } parser.nextToken(); parser.skipChildren(); } protected IOException _reportProblem(JsonParser p) { return JSONObjectException.from(p, "Unexpected token "+p.getCurrentToken()+"; should get FIELD_NAME or END_OBJECT"); } } ClassKey.java000066400000000000000000000050051323200335100342740ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; /** * Key class, used as an efficient and accurate key * for locating per-class values from {@link java.util.Map}s. *

* The reason for having a separate key class instead of * directly using {@link Class} as key is mostly * to allow for redefining hashCode method -- * for some strange reason, {@link Class} does not * redefine {@link Object#hashCode} and thus uses identity * hash, which is pretty slow. This makes key access using * {@link Class} unnecessarily slow. *

* Note: since class is not strictly immutable, caller must * know what it is doing, if changing field values. */ public final class ClassKey { private String _className; private Class _class; /** * Additional discriminator flags that may be used to allow * variations for same class. * * @since 2.8 */ private int _flags; /** * Let's cache hash code straight away, since we are * almost certain to need it. */ private int _hashCode; public ClassKey() { _class = null; _className = null; _flags = _hashCode = 0; } public ClassKey(Class clz, int flags) { _class = clz; _flags = flags; _className = clz.getName(); _hashCode = _className.hashCode() + flags; } public ClassKey with(Class clz, int flags) { _class = clz; _className = clz.getName(); _hashCode = _className.hashCode() + flags; _flags = flags; return this; } /* /********************************************************** /* Standard methods /********************************************************** */ @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != getClass()) return false; ClassKey other = (ClassKey) o; /* Is it possible to have different Class object for same name + class loader combo? * Let's assume answer is no: if this is wrong, will need to uncomment following functionality */ /* return (other._flags == _flags) && (other._className.equals(_className)) && (other._class.getClassLoader() == _class.getClassLoader()); */ return (other._flags == _flags) && (other._class == _class); } @Override public int hashCode() { return _hashCode; } @Override public String toString() { return _className; } } CollectionBuilder.java000066400000000000000000000176251323200335100361730ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import java.lang.reflect.Array; import java.util.*; import com.fasterxml.jackson.jr.ob.JSON.Feature; /** * Helper class that is used for constructing {@link java.util.Collection}s * to map JSON Array values in. *

* Objects server both as "factories" for creating new builders (blueprint * style), and as actual builders. For each distinct read operation, * {@link #newBuilder} will be called at least once; this instance * may be used and reused multiple times, as calling {@link #start} * will reset the state so that more {@link Collection}s may be built. */ public abstract class CollectionBuilder { protected final static Object[] EMPTY_ARRAY = new Object[0]; protected final int _features; /** * Optional {@link Collection} implementation class, used when specific * implementation is desired. */ protected final Class _collectionType; /* /********************************************************************** /* Construction /********************************************************************** */ protected CollectionBuilder(int features, Class collImpl) { _features = features; _collectionType = collImpl; } /** * Factory method for getting a blueprint instance of the default * {@link CollectionBuilder} implementation. */ public static CollectionBuilder defaultImpl() { return new Default(0, null); } public abstract CollectionBuilder newBuilder(int features); public abstract CollectionBuilder newBuilder(Class collImpl); public CollectionBuilder newBuilder() { return newBuilder(_features); } /* /********************************************************************** /* Simple accessors /********************************************************************** */ public final boolean isEnabled(Feature f) { return f.isEnabled(_features); } /* /********************************************************************** /* Actual building /********************************************************************** */ public abstract CollectionBuilder start(); public abstract CollectionBuilder add(Object value); /** * The usual build method to use for constructing {@link Collection} */ public abstract Collection buildCollection(); /** * Alternative build method used when desired result type is * Object[] */ public Object[] buildArray() { // sub-optimal, but defined for convenience Collection l = buildCollection(); return l.toArray(new Object[l.size()]); } @SuppressWarnings("unchecked") public T[] buildArray(Class type) { // as above, sub-optimal etc, but works Collection l = buildCollection(); Object[] a = (Object[]) Array.newInstance(type, l.size()); return (T[]) l.toArray(a); } /* /********************************************************************** /* More specialized build methods /********************************************************************** */ /** * Specialized method that is called when an empty Collection needs to * be constructed; this may be a new Collection, or an immutable shared * one, depending on implementation. *

* Default implementation simply calls: *

     *  start().buildCollection();
     *
*/ public Collection emptyCollection() { return start().buildCollection(); } /** * Specialized method that is called when an empty Object[] needs to * be returned. *

* Default implementation simply returns a shared empty array instance. */ public Object[] emptyArray() { return EMPTY_ARRAY; } @SuppressWarnings("unchecked") public T[] emptyArray(Class type) { if (type == Object.class) { return (T[]) EMPTY_ARRAY; } return (T[]) Array.newInstance(type, 0); } /** * Specialized method that is called when a single-entry Collection needs to * be constructed. *

* Default implementation simply calls: *

     *  start().add(value).buildCollection();
     *
*/ public Collection singletonCollection(Object value) { return start().add(value).buildCollection(); } /** * Specialized method that is called when a single-entry array needs to * be constructed. *

* Default implementation simply returns equivalent of: *

     *   new Object[] { value }
     *
*/ public Object[] singletonArray(Object value) { Object[] result = new Object[1]; result[0] = value; return result; } public T[] singletonArray(Class type, T value) { @SuppressWarnings("unchecked") T[] result = (T[]) Array.newInstance(type, 1); result[0] = value; return result; } /* /********************************************************************** /* Default implementations /********************************************************************** */ /** * Default {@link CollectionBuilder} implementation, which uses {@link ArrayList} * as the type of {@link java.util.List} to build, unless instructed otherwise. *

* When sub-classing to use different underlying mutable {@link java.util.List} * type, you need to sub-class following methods: *

    *
  • {@link #newBuilder}: factory method for constructing new builder instance *
  • *
  • {@link #_list}: factory method for constructing {@link java.util.List} to build *
  • *
*

* If constructing builders that use different approaches (like, say, produce * immutable Guava Lists), you may need to override more methods; or perhaps * just extend basic {@link CollectionBuilder}. */ public static class Default extends CollectionBuilder { protected Collection _current; protected Default(int features, Class collImpl) { super(features, collImpl); } @Override public CollectionBuilder newBuilder(int features) { return new Default(features, null); } @Override public CollectionBuilder newBuilder(Class collType) { return new Default(_features, collType); } @Override public CollectionBuilder start() { // If this builder is "busy", create a new one... if (_current != null) { return newBuilder().start(); } _current = _list(12); return this; } @Override public Collection buildCollection() { Collection result = _current; _current = null; return result; } @Override public Object[] buildArray() { Collection l = _current; _current = null; final int len = l.size(); Object[] result = new Object[len]; l.toArray(result); return result; } @Override public CollectionBuilder add(Object value) { _current.add(value); return this; } @Override public Collection emptyCollection() { if ((_collectionType == null) && isEnabled(Feature.READ_ONLY)) { return Collections.emptyList(); } return _list(0); } /** * Overridable factory method for constructing underlying List. */ protected Collection _list(int initialSize) { return new ArrayList(initialSize); } } } CollectionReader.java000066400000000000000000000045311323200335100357770ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.jr.ob.JSONObjectException; /** * Reader for typed {@link java.util.Collection} values. */ public class CollectionReader extends ValueReader { protected final Class _collectionType; protected final ValueReader _valueReader; public CollectionReader(Class t, ValueReader vr) { // some cleanup will be needed.... if (t == Collection.class || t == List.class) { // since we default to ArrayList _collectionType = null; } else if (t == Set.class) { _collectionType = HashSet.class; } else if (t == SortedSet.class) { _collectionType = TreeSet.class; } else { _collectionType = t; } _valueReader = vr; } @Override public Object readNext(JSONReader r, JsonParser p) throws IOException { if (p.nextToken() != JsonToken.START_ARRAY) { if (p.hasToken(JsonToken.VALUE_NULL)) { return null; } return JSONObjectException.from(p, "Unexpected token "+p.getCurrentToken()+"; should get START_ARRAY"); } CollectionBuilder b = r._collectionBuilder(_collectionType); if (p.nextToken() == JsonToken.END_ARRAY) { return b.emptyCollection(); } Object value = _valueReader.read(r, p); if (p.nextToken() == JsonToken.END_ARRAY) { return b.singletonCollection(value); } b = b.start().add(value); do { b = b.add(_valueReader.read(r, p)); } while (p.nextToken() != JsonToken.END_ARRAY); return b.buildCollection(); } @Override public Object read(JSONReader r, JsonParser p) throws IOException { CollectionBuilder b = r._collectionBuilder(_collectionType); if (p.nextToken() == JsonToken.END_ARRAY) { return b.emptyCollection(); } Object value = _valueReader.read(r, p); if (p.nextToken() == JsonToken.END_ARRAY) { return b.singletonCollection(value); } b = b.start().add(value); do { b = b.add(_valueReader.read(r, p)); } while (p.nextToken() != JsonToken.END_ARRAY); return b.buildCollection(); } }DeferredMap.java000066400000000000000000000104741323200335100347420ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import java.util.*; /** * A specialized {@link java.util.Map} implementation that will collect * entries during building, but only materialize full lookup structure * when needed; that is, actual building of hash lookup is deferred. *

* Inspired by lazily initialized Map used by Boon library. */ public class DeferredMap extends AbstractMap { private Map _map; private Object[] _entries; private int _end; private final boolean _ordered; public DeferredMap(boolean ordered) { this(ordered, 4); } public DeferredMap(boolean ordered, int initialSize) { _ordered = ordered; } @Override public Object put(Object key, Object value) { if (_map == null) { if (_entries == null) { _entries = new Object[8]; } else if (_end == _entries.length) { final int newSize = _newSize(_end); _entries = Arrays.copyOf(_entries, newSize); } _entries[_end] = key; _entries[++_end] = value; ++_end; // here's assuming no dups are added return null; } return _map.put(key, value); } @Override public Set> entrySet() { buildIfNeeded(); return _map.entrySet(); } @Override public int size() { // assuming no dups; otherwise could overestimate return (_map == null) ? (_end >> 1) : _map.size(); } @Override public boolean isEmpty() { return (_map == null) ? (_end == 0) : _map.isEmpty(); } @Override public boolean containsValue(Object value) { buildIfNeeded(); return _map.containsValue(value); } @Override public boolean containsKey(Object key) { buildIfNeeded(); return _map.containsKey(key); } @Override public Object get(Object key) { buildIfNeeded(); return _map.get( key ); } @Override public Object remove(Object key) { buildIfNeeded(); return _map.remove( key ); } @Override public void clear() { if (_map != null ) { _map.clear(); } else { _end = 0; } } @Override public Set keySet() { buildIfNeeded(); return _map.keySet(); } @Override public Collection values() { buildIfNeeded(); return _map.values(); } @Override public boolean equals(Object other) { buildIfNeeded(); return _map.equals(other); } @Override public int hashCode() { buildIfNeeded(); return _map.hashCode(); } @Override public String toString() { buildIfNeeded(); return _map.toString(); } @Override protected Object clone() throws CloneNotSupportedException { buildIfNeeded(); if (_map instanceof HashMap) { return ((HashMap)_map).clone(); } return new HashMap(_map); } protected void buildIfNeeded() { if (_map == null) { // translate from entry count (which is 2 * size) bit down; trying to avoid // having to resize... i.e. use 3/4 of entry count _map = _buildMap(_end >> 2); for (int i = 0; i < _end; i += 2) { _map.put((String) _entries[i], _entries[i+1]); } _entries = null; } } private final int _newSize(int size) { if (size < 200) { return size+size; } // note: MUST ensure it's divisible by two (that is, last bit is 0), because // always adding values in pairs, but checking size before add if (size < 2000) { return size + ((size>>1) & ~1); } return size + ((size>>2) & ~1); } protected Map _buildMap(int expSize) { int size; if (expSize < 4) { size = 4; } else { // should add ~1/3 as size is rounded up to power of 3 size = expSize + (3 * (expSize >> 3)); } if (_ordered) { return new LinkedHashMap(size); } return new HashMap(size); } } EnumReader.java000066400000000000000000000035571323200335100346170ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import java.io.IOException; import java.util.Map; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.jr.ob.JSONObjectException; /** * Reader for Enum values: needed because we need a simple {@link java.util.Map} * for efficient conversion from id (gotten with {@link java.lang.Enum#toString()} * to value. *

* In future we could consider alternatively allowing use of * {@link java.lang.Enum#name()} for id. */ public class EnumReader extends ValueReader { protected final Object[] _byIndex; protected final Map _byName; public EnumReader(Object[] byIndex, Map byName) { _byIndex = byIndex; _byName = byName; } private String desc() { return _byIndex[0].getClass().getName(); } @Override public Object readNext(JSONReader reader, JsonParser p) throws IOException { String name = p.nextTextValue(); if (name != null) { return _enum(name); } return read(reader, p); } @Override public Object read(JSONReader reader, JsonParser p) throws IOException { if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) { int ix = p.getIntValue(); if (ix < 0 || ix >= _byIndex.length) { throw new JSONObjectException("Failed to bind Enum "+desc()+" with index "+ix +" (has "+_byIndex.length+" values)"); } return _byIndex[ix]; } return _enum(p.getValueAsString().trim()); } private Object _enum(String id) throws IOException { Object e = _byName.get(id); if (e == null) { throw new JSONObjectException("Failed to find Enum of type "+desc()+" for value '"+id+"'"); } return e; } }JSONAsObjectCodec.java000066400000000000000000000150041323200335100357000ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import java.io.IOException; import java.util.Iterator; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.ResolvedType; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.jr.ob.JSON; import com.fasterxml.jackson.jr.ob.JSONObjectException; import com.fasterxml.jackson.jr.ob.PackageVersion; /** * Convenience wrapper around {@link JSON} that implements {@link ObjectCodec}. * Note that implementation is not complete, due to natural limitations of * {@link JSON} and "simple" object binding. *

* The main use case is to give minimal context for other components that * expect to get a {@link ObjectCodec}, such as {@link JsonParser} and * {@link JsonGenerator}. */ public class JSONAsObjectCodec extends ObjectCodec { protected final JSON _json; protected final JsonFactory _jsonFactory; protected final TreeCodec _treeCodec; public JSONAsObjectCodec(JSON json) { this(json, json.getStreamingFactory()); } public JSONAsObjectCodec(JSON json, JsonFactory jf) { this(json, jf, json.getTreeCodec()); } public JSONAsObjectCodec(JSON json, JsonFactory jf, TreeCodec treeCodec) { _json = json; _jsonFactory = jf; _treeCodec = treeCodec; } @Override public Version version() { return PackageVersion.VERSION; } /* /********************************************************************** /* ObjectCodec: Object reads /********************************************************************** */ @SuppressWarnings("unchecked") @Override public T readValue(JsonParser jp, Class valueType) throws IOException, JsonProcessingException { Object ob = _json.anyFrom(jp); _checkResultType(valueType, ob); return (T) ob; } @Override public T readValue(JsonParser jp, TypeReference valueTypeRef) throws IOException, JsonProcessingException { throw _noTypeReference(); } @SuppressWarnings("unchecked") @Override public T readValue(JsonParser jp, ResolvedType valueType) throws IOException, JsonProcessingException { return (T) readValue(jp, valueType.getRawClass()); } @Override public Iterator readValues(JsonParser jp, Class valueType) throws IOException, JsonProcessingException { // May be able to support in future but... throw new JSONObjectException("Simple JSON does not support 'readValues()' methods"); } @Override public Iterator readValues(JsonParser jp, TypeReference valueTypeRef) throws IOException, JsonProcessingException { throw _noTypeReference(); } @SuppressWarnings("unchecked") @Override public Iterator readValues(JsonParser jp, ResolvedType valueType) throws IOException, JsonProcessingException { return (Iterator) readValues(jp, valueType.getRawClass()); } protected JSONObjectException _noTypeReference() { return new JSONObjectException("Simple JSON does not support use of TypeReference"); } /* /********************************************************************** /* ObjectCodec: Object writes /********************************************************************** */ @Override public void writeValue(JsonGenerator jgen, Object value) throws IOException, JsonProcessingException { _json.write(value, jgen); } /* /********************************************************************** /* ObjectCodec: Tree /********************************************************************** */ @Override public TreeNode createObjectNode() { return _checkTreeCodec().createObjectNode(); } @Override public TreeNode createArrayNode() { return _checkTreeCodec().createArrayNode(); } @Override public T readTree(JsonParser jp) throws IOException, JsonProcessingException { return _checkTreeCodec().readTree(jp); } @Override public void writeTree(JsonGenerator jg, TreeNode tree) throws IOException, JsonProcessingException { _checkTreeCodec().writeTree(jg, tree); } @Override public JsonParser treeAsTokens(TreeNode n) { return _checkTreeCodec().treeAsTokens(n); } @Override public T treeToValue(TreeNode n, Class valueType) throws JsonProcessingException { /* Without TokenBuffer from jackson-databind, need to actually * create an intermediate textual representation. Fine, * we should be able to do that. Bigger question is whether * actual read works but... */ try { String json = _json.asString(n); JsonParser jp = _jsonFactory.createParser(json); T result = readValue(jp, valueType); jp.close(); return result; } catch (JsonProcessingException e) { // to support [JACKSON-758] throw e; } catch (IOException e) { // shouldn't really happen, but is declared as possibility so: throw JSONObjectException.fromUnexpectedIOE(e); } } /* /********************************************************************** /* ObjectCodec: other /********************************************************************** */ @Override public JsonFactory getFactory() { return _jsonFactory; } @Deprecated @Override public JsonFactory getJsonFactory() { return _jsonFactory; } /* /********************************************************************** /* Internal methods /********************************************************************** */ protected TreeCodec _checkTreeCodec() { TreeCodec c = _treeCodec; if (c == null) { throw new IllegalStateException("No TreeCodec has been configured: can not use tree operations"); } return c; } protected void _checkResultType(Class valueType, Object ob) throws JSONObjectException { if (ob != null) { if (!valueType.isAssignableFrom(ob.getClass())) { throw new JSONObjectException("Simple JSON can only bind given JSON as " +ob.getClass().getName()+", not as "+valueType.getName()); } } } } JSONReader.java000066400000000000000000000252121323200335100344540ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import java.io.*; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.jr.ob.JSONObjectException; import com.fasterxml.jackson.jr.ob.JSON.Feature; /** * Object that handles construction of simple Objects from JSON. *

* Life-cycle is such that initial instance (called blueprint) * is constructed first (including possible configuration * using mutant factory methods). This blueprint object * acts as a factory, and is never used for direct writing; * instead, per-call instance is created by calling * {@link #perOperationInstance}. */ public class JSONReader extends ValueReader // just to get convenience methods { /* /********************************************************************** /* Blueprint config /********************************************************************** */ protected final int _features; protected final TreeCodec _treeCodec; /** * Object that is used to resolve types of values dynamically. */ protected final TypeDetector _typeDetector; /** * Handler that takes care of constructing {@link java.util.Map}s as needed */ protected final MapBuilder _mapBuilder; /** * Handler that takes care of constructing {@link java.util.Map}s as needed */ protected final CollectionBuilder _collectionBuilder; /* /********************************************************************** /* Instance config, state /********************************************************************** */ protected final JsonParser _parser; /* /********************************************************************** /* Blueprint construction /********************************************************************** */ /** * Constructor used for creating the blueprint instances. */ public JSONReader(int features, TypeDetector td, TreeCodec treeCodec, CollectionBuilder lb, MapBuilder mb) { _features = features; _typeDetector = td; _treeCodec = treeCodec; _collectionBuilder = lb; _mapBuilder = mb; _parser = null; } /** * Constructor used for per-operation (non-blueprint) instance. */ protected JSONReader(JSONReader base, int features, TypeDetector td, JsonParser p) { _features = features; _typeDetector = td; _treeCodec = base._treeCodec; _collectionBuilder = base._collectionBuilder.newBuilder(features); _mapBuilder = base._mapBuilder.newBuilder(features); _parser = p; } @Override public Object read(JSONReader reader, JsonParser p) throws IOException { // never to be called for this instance throw new UnsupportedOperationException(); } @Override public Object readNext(JSONReader reader, JsonParser p) throws IOException { // never to be called for this instance throw new UnsupportedOperationException(); } /* /********************************************************************** /* Mutant factories for blueprint /********************************************************************** */ public JSONReader withFeatures(int features) { if (_features == features) { return this; } return _with(features, _typeDetector, _treeCodec, _collectionBuilder, _mapBuilder); } public JSONReader with(MapBuilder mb) { if (_mapBuilder == mb) return this; return _with(_features, _typeDetector, _treeCodec, _collectionBuilder, mb); } public JSONReader with(CollectionBuilder lb) { if (_collectionBuilder == lb) return this; return _with(_features, _typeDetector, _treeCodec, lb, _mapBuilder); } /** * Overridable method that all mutant factories call if a new instance * is to be constructed */ protected JSONReader _with(int features, TypeDetector td, TreeCodec tc, CollectionBuilder lb, MapBuilder mb) { if (getClass() != JSONReader.class) { // sanity check throw new IllegalStateException("Sub-classes MUST override _with(...)"); } return new JSONReader(features, td, tc, lb, mb); } /* /********************************************************************** /* New instance creation /********************************************************************** */ public JSONReader perOperationInstance(int features, JsonParser p) { if (getClass() != JSONReader.class) { // sanity check throw new IllegalStateException("Sub-classes MUST override perOperationInstance(...)"); } return new JSONReader(this, features, _typeDetector.perOperationInstance(features), p); } /* /********************************************************************** /* Simple accessors /********************************************************************** */ /** * @since 2.8 */ public boolean arraysAsLists() { return Feature.READ_JSON_ARRAYS_AS_JAVA_ARRAYS.isDisabled(_features); } /* /********************************************************************** /* Public entry points for reading Simple objects from JSON /********************************************************************** */ /** * Method for reading a "simple" Object of type indicated by JSON * content: {@link java.util.Map} for JSON Object, {@link java.util.Map} * for JSON Array (or, Object[] if so configured), * {@link java.lang.String} for JSON String value and so on. */ public Object readValue() throws IOException { return AnyReader.std.read(this, _parser); } /** * Method for reading a JSON Object from input and building a {@link java.util.Map} * out of it. Note that if input does NOT contain a * JSON Object, {@link JSONObjectException} will be thrown. */ public Map readMap() throws IOException { JsonToken t = _parser.getCurrentToken(); if (t == JsonToken.VALUE_NULL) { return null; } if (t != JsonToken.START_OBJECT) { throw JSONObjectException.from(_parser, "Can not read a Map: expect to see START_OBJECT ('{'), instead got: "+_tokenDesc(_parser)); } return AnyReader.std.readFromObject(this, _parser, _mapBuilder); } /** * Method for reading a JSON Array from input and building a {@link java.util.List} * out of it. Note that if input does NOT contain a * JSON Array, {@link JSONObjectException} will be thrown. */ public List readList() throws IOException { JsonToken t = _parser.getCurrentToken(); if (t == JsonToken.VALUE_NULL) { return null; } if (t != JsonToken.START_ARRAY) { throw JSONObjectException.from(_parser, "Can not read a List: expect to see START_ARRAY ('['), instead got: "+_tokenDesc(_parser)); } return (List) AnyReader.std.readCollectionFromArray(this, _parser, _collectionBuilder); } /** * Method for reading a JSON Array from input and building a Object[] * out of it. Note that if input does NOT contain a * JSON Array, {@link JSONObjectException} will be thrown. */ public Object[] readArray() throws IOException { JsonToken t = _parser.getCurrentToken(); if (t == JsonToken.VALUE_NULL) { return null; } if (t != JsonToken.START_ARRAY) { throw JSONObjectException.from(_parser, "Can not read an array: expect to see START_ARRAY ('['), instead got: "+_tokenDesc(_parser)); } return AnyReader.std.readArrayFromArray(this, _parser, _collectionBuilder); } /* /********************************************************************** /* Public entry points for reading (more) typed types /********************************************************************** */ /** * Method for reading a JSON Object from input and building a Bean of * specified type out of it; Bean has to conform to standard Java Bean * specification by having setters for passing JSON Object properties. */ @SuppressWarnings("unchecked") public T readBean(Class type) throws IOException { ValueReader vr = _typeDetector.findReader(type); return (T) vr.read(this, _parser); } @SuppressWarnings("unchecked") public T[] readArrayOf(Class type) throws IOException { JsonToken t = _parser.getCurrentToken(); if (t == JsonToken.VALUE_NULL) { return null; } if (t != JsonToken.START_ARRAY) { throw JSONObjectException.from(_parser, "Can not read an array: expect to see START_ARRAY ('['), instead got: "+_tokenDesc(_parser)); } return (T[]) new ArrayReader(type, _typeDetector.findReader(type)).read(this, _parser); } /** * Method for reading a JSON Array from input and building a {@link java.util.List} * out of it. Note that if input does NOT contain a * JSON Array, {@link JSONObjectException} will be thrown. */ @SuppressWarnings("unchecked") public List readListOf(Class type) throws IOException { JsonToken t = _parser.getCurrentToken(); if (t == JsonToken.VALUE_NULL) { return null; } if (t != JsonToken.START_ARRAY) { throw JSONObjectException.from(_parser, "Can not read a List: expect to see START_ARRAY ('['), instead got: "+_tokenDesc(_parser)); } return (List) new CollectionReader(List.class, _typeDetector.findReader(type)).read(this, _parser); } /* /********************************************************************** /* Internal methods; overridable for custom coercions /********************************************************************** */ protected TreeCodec _treeCodec() throws JSONObjectException { if (_treeCodec == null) { throw new JSONObjectException("No TreeCodec specified: can not bind JSON into TreeNode types"); } return _treeCodec; } protected MapBuilder _mapBuilder(Class mapType) { return (mapType == null) ? _mapBuilder : _mapBuilder.newBuilder(mapType); } protected CollectionBuilder _collectionBuilder(Class collType) { return (collType == null) ? _collectionBuilder : _collectionBuilder.newBuilder(collType); } } JSONWriter.java000066400000000000000000000601001323200335100345210ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import java.io.*; import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.SerializedString; import com.fasterxml.jackson.jr.ob.JSONObjectException; import com.fasterxml.jackson.jr.ob.JSON.Feature; import static com.fasterxml.jackson.jr.ob.impl.TypeDetector.*; /** * Object that handles serialization of simple Objects into * JSON. *

* Life-cycle is such that initial instance (called blueprint) * is constructed first (including possible configuration * using mutant factory methods). This blueprint object * acts as a factory, and is never used for direct writing; * instead, per-call instance is created by calling * {@link #perOperationInstance}. */ public class JSONWriter { private final static TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC"); /* /********************************************************************** /* Blueprint config /********************************************************************** */ protected final int _features; protected final boolean _writeNullValues; /** * Object that is used to resolve types of values dynamically. */ protected final TypeDetector _typeDetector; protected final TreeCodec _treeCodec; /* /********************************************************************** /* Instance config /********************************************************************** */ protected final JsonGenerator _generator; protected final TimeZone _timezone; /* /********************************************************************** /* Blueprint construction /********************************************************************** */ /** * Constructor used for creating differently configured blueprint * instances */ public JSONWriter(int features, TypeDetector td, TreeCodec tc) { _features = features; _writeNullValues = Feature.WRITE_NULL_PROPERTIES.isEnabled(features); _typeDetector = td; _treeCodec = tc; _generator = null; _timezone = DEFAULT_TIMEZONE; } /** * Constructor for non-blueprint instances */ protected JSONWriter(JSONWriter base, int features, TypeDetector td, JsonGenerator g) { _features = features; _writeNullValues = Feature.WRITE_NULL_PROPERTIES.isEnabled(features); _typeDetector = td; _treeCodec = base._treeCodec; _generator = g; _timezone = DEFAULT_TIMEZONE; } /* /********************************************************************** /* Mutant factories for blueprint /********************************************************************** */ public JSONWriter with(TreeCodec tc) { if (_treeCodec == tc) { return this; } return _with(_features, _typeDetector, tc); } /** * Overridable method that all mutant factories call if a new instance * is to be constructed */ protected JSONWriter _with(int features, TypeDetector td, TreeCodec tc) { if (getClass() != JSONWriter.class) { // sanity check throw new IllegalStateException("Sub-classes MUST override _with(...)"); } return new JSONWriter(features, td, tc); } /* /********************************************************************** /* New instance creation /********************************************************************** */ public JSONWriter perOperationInstance(int features, JsonGenerator g) { if (getClass() != JSONWriter.class) { // sanity check throw new IllegalStateException("Sub-classes MUST override perOperationInstance(...)"); } return new JSONWriter(this, features, _typeDetector.perOperationInstance(features), g); } /* /********************************************************************** /* Public entry methods /********************************************************************** */ public void writeValue(Object value) throws IOException { if (value == null) { writeNullValue(); return; } _writeValue(value, _typeDetector.findSerializationType(value.getClass())); } @Deprecated // since 2.8 public void writeField(String fieldName, Object value) throws IOException { if (value == null) { if (_writeNullValues) { writeNullField(fieldName); } return; } writeField(fieldName, value, _typeDetector.findSerializationType(value.getClass())); } public void writeField(String fieldName, Object value, int type) throws IOException { switch (type) { // Structured types: case SER_MAP: writeMapField(fieldName, (Map) value); return; case SER_LIST: writeListField(fieldName, (List) value); return; case SER_COLLECTION: writeCollectionField(fieldName, (Collection) value); return; case SER_OBJECT_ARRAY: writeObjectArrayField(fieldName, (Object[]) value); return; case SER_INT_ARRAY: writeIntArrayField(fieldName, (int[]) value); return; case SER_LONG_ARRAY: writeLongArrayField(fieldName, (long[]) value); return; case SER_BOOLEAN_ARRAY: writeBooleanArrayField(fieldName, (boolean[]) value); return; case SER_TREE_NODE: writeTreeNodeField(fieldName, (TreeNode) value); return; // Textual types, similar: case SER_STRING: writeStringField(fieldName, (String) value); return; case SER_CHAR_ARRAY: writeStringField(fieldName, new String((char[]) value)); return; case SER_CHARACTER_SEQUENCE: writeStringField(fieldName, ((CharSequence) value).toString()); return; case SER_BYTE_ARRAY: writeBinaryField(fieldName, (byte[]) value); return; // Number types: case SER_NUMBER_BIG_DECIMAL: writeBigDecimalField(fieldName, (BigDecimal) value); return; case SER_NUMBER_BIG_INTEGER: writeBigIntegerField(fieldName, (BigInteger) value); return; case SER_NUMBER_FLOAT: // fall through case SER_NUMBER_DOUBLE: writeDoubleField(fieldName, ((Number) value).doubleValue()); return; case SER_NUMBER_BYTE: // fall through case SER_NUMBER_SHORT: // fall through case SER_NUMBER_INTEGER: writeIntField(fieldName, ((Number) value).intValue()); return; case SER_NUMBER_LONG: writeLongField(fieldName, ((Number) value).longValue()); return; // Scalar types: case SER_BOOLEAN: writeBooleanField(fieldName, ((Boolean) value).booleanValue()); return; case SER_CHAR: writeStringField(fieldName, String.valueOf(value)); return; case SER_CALENDAR: writeDateField(fieldName, ((Calendar) value).getTime()); return; case SER_DATE: writeDateField(fieldName, (Date) value); return; case SER_ENUM: writeEnumField(fieldName, (Enum) value); return; case SER_CLASS: writeStringLikeField(fieldName, ((Class) value).getName(), type); return; case SER_FILE: writeStringLikeField(fieldName, ((File) value).getAbsolutePath(), type); return; case SER_UUID: case SER_URL: case SER_URI: writeStringLikeField(fieldName, value.toString(), type); return; // Others case SER_ITERABLE: writeIterableField(fieldName, (Iterable) value); return; case SER_UNKNOWN: writeUnknownField(fieldName, value); return; } if (type < 0) { // Bean type! BeanPropertyWriter[] props = _typeDetector.getPropertyWriters(type); if (props != null) { // sanity check _generator.writeFieldName(fieldName); writeBeanValue(props, value); return; } } _badType(type, value); } protected void _writeValue(Object value, int type) throws IOException { switch (type) { // Structured types: case SER_MAP: writeMapValue((Map) value); return; case SER_LIST: writeListValue((List) value); return; case SER_COLLECTION: writeCollectionValue((Collection) value); return; case SER_OBJECT_ARRAY: writeObjectArrayValue((Object[]) value); return; case SER_INT_ARRAY: writeIntArrayValue((int[]) value); return; case SER_LONG_ARRAY: writeLongArrayValue((long[]) value); return; case SER_BOOLEAN_ARRAY: writeBooleanArrayValue((boolean[]) value); return; case SER_TREE_NODE: writeTreeNodeValue((TreeNode) value); return; // Textual types, related: case SER_STRING: writeStringValue((String) value); return; case SER_CHAR_ARRAY: writeStringValue(new String((char[]) value)); return; case SER_CHARACTER_SEQUENCE: writeStringValue(((CharSequence) value).toString()); return; case SER_BYTE_ARRAY: writeBinaryValue((byte[]) value); return; // Number types: case SER_NUMBER_FLOAT: // fall through case SER_NUMBER_DOUBLE: writeDoubleValue(((Number) value).doubleValue()); return; case SER_NUMBER_BYTE: // fall through case SER_NUMBER_SHORT: // fall through case SER_NUMBER_INTEGER: writeIntValue(((Number) value).intValue()); return; case SER_NUMBER_LONG: writeLongValue(((Number) value).longValue()); return; case SER_NUMBER_BIG_DECIMAL: writeBigDecimalValue((BigDecimal) value); return; case SER_NUMBER_BIG_INTEGER: writeBigIntegerValue((BigInteger) value); return; // Other scalar types: case SER_BOOLEAN: writeBooleanValue(((Boolean) value).booleanValue()); return; case SER_CHAR: writeStringValue(String.valueOf(value)); return; case SER_CALENDAR: writeDateValue(((Calendar) value).getTime()); return; case SER_DATE: writeDateValue((Date) value); return; case SER_ENUM: writeEnumValue((Enum) value); return; case SER_CLASS: writeStringLikeValue(((Class) value).getName(), type); return; case SER_FILE: writeStringLikeValue(((File) value).getAbsolutePath(), type); return; // these type should be fine using toString() case SER_UUID: case SER_URL: case SER_URI: writeStringLikeValue(value.toString(), type); return; case SER_ITERABLE: writeIterableValue((Iterable) value); return; case SER_UNKNOWN: writeUnknownValue(value); return; } if (type < 0) { // Bean type! BeanPropertyWriter[] props = _typeDetector.getPropertyWriters(type); if (props != null) { // sanity check writeBeanValue(props, value); return; } } _badType(type, value); } /* /********************************************************************** /* Overridable concrete typed write methods, structured types /********************************************************************** */ protected void writeCollectionValue(Collection v) throws IOException { _generator.writeStartArray(); for (Object ob : v) { writeValue(ob); } _generator.writeEndArray(); } protected void writeCollectionField(String fieldName, Collection v) throws IOException { _generator.writeFieldName(fieldName); writeCollectionValue(v); } protected void writeIterableValue(Iterable v) throws IOException { _generator.writeStartArray(); for (Object ob : v) { writeValue(ob); } _generator.writeEndArray(); } protected void writeIterableField(String fieldName, Iterable v) throws IOException { _generator.writeFieldName(fieldName); writeIterableValue(v); } protected void writeListValue(List list) throws IOException { _generator.writeStartArray(); for (int i = 0, len = list.size(); i < len; ++i) { Object value = list.get(i); if (value == null) { _generator.writeNull(); continue; } _writeValue(value, _typeDetector.findSerializationType(value.getClass())); } _generator.writeEndArray(); } protected void writeListField(String fieldName, List v) throws IOException { _generator.writeFieldName(fieldName); writeListValue(v); } protected void writeMapValue(Map v) throws IOException { _generator.writeStartObject(); if (!v.isEmpty()) { for (Map.Entry entry : v.entrySet()) { String key = keyToString(entry.getKey()); Object value = entry.getValue(); if (value == null) { if (_writeNullValues) { writeNullField(key); } continue; } Class cls = value.getClass(); int type = _typeDetector.findSerializationType(cls); writeField(key, value, type); } } _generator.writeEndObject(); } protected void writeMapField(String fieldName, Map v) throws IOException { _generator.writeFieldName(fieldName); writeMapValue(v); } protected void writeObjectArrayValue(Object[] v) throws IOException { _generator.writeStartArray(); for (int i = 0, len = v.length; i < len; ++i) { writeValue(v[i]); } _generator.writeEndArray(); } protected void writeObjectArrayField(String fieldName, Object[] v) throws IOException { _generator.writeFieldName(fieldName); writeObjectArrayValue(v); } protected void writeIntArrayValue(int[] v) throws IOException { _generator.writeStartArray(); for (int i = 0, len = v.length; i < len; ++i) { _generator.writeNumber(v[i]); } _generator.writeEndArray(); } protected void writeIntArrayField(String fieldName, int[] v) throws IOException { _generator.writeFieldName(fieldName); writeIntArrayValue(v); } protected void writeLongArrayValue(long[] v) throws IOException { _generator.writeStartArray(); for (int i = 0, len = v.length; i < len; ++i) { _generator.writeNumber(v[i]); } _generator.writeEndArray(); } protected void writeLongArrayField(String fieldName, long[] v) throws IOException { _generator.writeFieldName(fieldName); writeLongArrayValue(v); } protected void writeBooleanArrayValue(boolean[] v) throws IOException { _generator.writeStartArray(); for (int i = 0, len = v.length; i < len; ++i) { _generator.writeBoolean(v[i]); } _generator.writeEndArray(); } protected void writeBooleanArrayField(String fieldName, boolean[] v) throws IOException { _generator.writeFieldName(fieldName); writeBooleanArrayValue(v); } protected void writeTreeNodeValue(TreeNode v) throws IOException { if (_treeCodec == null) { throw new JSONObjectException("No TreeCodec configured: can not serializer TreeNode values"); } _treeCodec.writeTree(_generator, v); } protected void writeTreeNodeField(String fieldName, TreeNode v) throws IOException { _generator.writeFieldName(fieldName); writeTreeNodeValue(v); } /* /********************************************************************** /* Overridable concrete typed write methods, primitives /********************************************************************** */ protected void writeBooleanValue(boolean v) throws IOException { _generator.writeBoolean(v); } protected void writeBooleanField(String fieldName, boolean v) throws IOException { _generator.writeBooleanField(fieldName, v); } protected void writeIntValue(int v) throws IOException { _generator.writeNumber(v); } protected void writeIntField(String fieldName, int v) throws IOException { _generator.writeNumberField(fieldName, v); } protected void writeLongValue(long v) throws IOException { _generator.writeNumber(v); } protected void writeBigIntegerValue(BigInteger v) throws IOException { _generator.writeNumber(v); } protected void writeBigIntegerField(String fieldName, BigInteger v) throws IOException { _generator.writeFieldName(fieldName); writeBigIntegerValue(v); } protected void writeLongField(String fieldName, long v) throws IOException { _generator.writeNumberField(fieldName, v); } protected void writeDoubleValue(double v) throws IOException { _generator.writeNumber(v); } protected void writeDoubleField(String fieldName, double v) throws IOException { _generator.writeNumberField(fieldName, v); } protected void writeBigDecimalValue(BigDecimal v) throws IOException { _generator.writeNumber(v); } protected void writeBigDecimalField(String fieldName, BigDecimal v) throws IOException { _generator.writeNumberField(fieldName, v); } /* /********************************************************************** /* Overridable concrete typed write methods, textual /********************************************************************** */ protected void writeStringValue(String v) throws IOException { _generator.writeString(v); } protected void writeStringField(String fieldName, String v) throws IOException { _generator.writeStringField(fieldName, v); } protected void writeStringLikeValue(String v, int actualType) throws IOException { _generator.writeString(v); } protected void writeStringLikeField(String fieldName, String v, int actualType) throws IOException { _generator.writeStringField(fieldName, v); } protected void writeBinaryValue(byte[] data) throws IOException { _generator.writeBinary(data); } protected void writeBinaryField(String fieldName, byte[] data) throws IOException { _generator.writeBinaryField(fieldName, data); } /* /********************************************************************** /* Overridable concrete typed write methods, other /********************************************************************** */ protected void writeNullValue() throws IOException { _generator.writeNull(); } protected void writeNullField(String fieldName) throws IOException { if (_writeNullValues) { _generator.writeNullField(fieldName); } } protected void writeNullField(SerializedString fieldName) throws IOException { if (_writeNullValues) { _generator.writeFieldName(fieldName); _generator.writeNull(); } } protected void writeDateValue(Date v) throws IOException { if (Feature.WRITE_DATES_AS_TIMESTAMP.isEnabled(_features)) { writeLongValue(v.getTime()); } else { writeStringValue(dateToString(v)); } } protected void writeDateField(String fieldName, Date v) throws IOException { if (Feature.WRITE_DATES_AS_TIMESTAMP.isEnabled(_features)) { writeLongField(fieldName, v.getTime()); } else { writeStringField(fieldName, dateToString(v)); } } protected void writeEnumValue(Enum v) throws IOException { if (Feature.WRITE_ENUMS_USING_INDEX.isEnabled(_features)) { writeIntValue(v.ordinal()); } else { writeStringValue(v.toString()); } } protected void writeEnumField(String fieldName, Enum v) throws IOException { if (Feature.WRITE_ENUMS_USING_INDEX.isEnabled(_features)) { writeIntField(fieldName, v.ordinal()); } else { writeStringField(fieldName, v.toString()); } } protected void writeBeanValue(BeanPropertyWriter[] props, Object bean) throws IOException { _generator.writeStartObject(); for (int i = 0, end = props.length; i < end; ++i) { BeanPropertyWriter property = props[i]; SerializedString name = property.name; Object value = property.getValueFor(bean); if (value == null) { if (_writeNullValues) { writeNullField(name); } continue; } int typeId = property.typeId; if (typeId == 0) { typeId = _typeDetector.findSerializationType(value.getClass()); } _generator.writeFieldName(name); _writeValue(value, typeId); } _generator.writeEndObject(); } protected void writeUnknownValue(Object data) throws IOException { _checkUnknown(data); writeStringValue(data.toString()); } protected void writeUnknownField(String fieldName, Object data) throws IOException { _checkUnknown(data); writeStringField(fieldName, data.toString()); } protected void _checkUnknown(Object value) throws IOException { if (Feature.FAIL_ON_UNKNOWN_TYPE_WRITE.isEnabled(_features)) { throw new JSONObjectException("Unrecognized type ("+value.getClass().getName() +"), don't know how to write (disable "+Feature.FAIL_ON_UNKNOWN_TYPE_WRITE +" to avoid exception)"); } } /* /********************************************************************** /* Overridable concrete typed write methods; key conversions: /********************************************************************** */ protected String keyToString(Object rawKey) { if (rawKey instanceof String) { return (String) rawKey; } return String.valueOf(rawKey); } /** * @since 2.7 */ protected String dateToString(Date v) { if (v == null) { return ""; } // !!! 01-Dec-2015, tatu: Should really use proper DateFormat or something // since this relies on system-wide defaults, and hard/impossible to // change easily return v.toString(); } /* /********************************************************************** /* Other internal methods /********************************************************************** */ private void _badType(int type, Object value) { if (type < 0) { throw new IllegalStateException(String.format( "Internal error: missing BeanDefinition for id %d (class %s)", type, value.getClass().getName())); } throw new IllegalStateException(String.format( "Unsupported type: %s (%s)", type, value.getClass().getName())); } } MapBuilder.java000066400000000000000000000137621323200335100346130ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import java.util.*; import com.fasterxml.jackson.jr.ob.JSON; import com.fasterxml.jackson.jr.ob.JSON.Feature; import com.fasterxml.jackson.jr.ob.JSONObjectException; /** * Helper class that is used for constructing {@link java.util.Map}s * to map JSON Object values in. *

* Objects server both as "factories" for creating new builders (blueprint * style), and as actual builders. For each distinct read operation, * {@link #newBuilder} will be called at least once; this instance * may be used and reused multiple times, as calling {@link #start} * will reset the state so that more {@link List}s may be built. */ public abstract class MapBuilder { protected final int _features; protected final boolean _checkDups; /** * Optional {@link Map} implementation class, used when specific * implementation is desired. */ protected final Class _mapType; protected MapBuilder(int features, Class type) { _features = features; _checkDups = JSON.Feature.FAIL_ON_DUPLICATE_MAP_KEYS.isEnabled(features); _mapType = type; } /** * Factory method for getting a blueprint instance of the default * {@link MapBuilder} implementation. */ public static MapBuilder defaultImpl() { return new Default(0, null); } public abstract MapBuilder newBuilder(int features); public abstract MapBuilder newBuilder(Class mapImpl); public MapBuilder newBuilder() { return newBuilder(_features); } public final boolean isEnabled(JSON.Feature f) { return f.isEnabled(_features); } public abstract MapBuilder start(); public abstract MapBuilder put(Object key, Object value); public abstract Map build(); /** * Specialized method that is called when an empty list needs to * be constructed; this may be a new list, or an immutable shared * List, depending on implementation. *

* Default implementation simply calls: *

     *  start().build();
     *
* which assumes that a builder has been constructed with {@link #newBuilder} */ public Map emptyMap() throws JSONObjectException { return start().build(); } /** * Specialized method that is called when an empty list needs to * be constructed; this may be a new list, or an immutable shared * List, depending on implementation. *

* Default implementation simply calls: *

     *  start().put(key, value).build();
     *
*/ public Map singletonMap(Object key, Object value) throws JSONObjectException { return start().put(key, value).build(); } /* /********************************************************** /* Default implementation /********************************************************** */ /** * Default {@link MapBuilder} implementation which builds * either {@link HashMap} or {@link LinkedHashMap} instances * (depending on {@link Feature#PRESERVE_FIELD_ORDERING}). * It may also, with alternate configuration, * use {@link Collections#emptyMap()} for empty Maps, * if allowed with {@link Feature#READ_ONLY}. */ public static class Default extends MapBuilder { protected Map _current; protected Default(int features, Class type) { super(features, type); } @Override public MapBuilder newBuilder(int features) { return new Default(features, _mapType); } @Override public MapBuilder newBuilder(Class mapImpl) { return new Default(_features, mapImpl); } @Override public MapBuilder start() { // If this builder is "busy", create a new one... if (_current != null) { return newBuilder().start(); } _current = _map(12); return this; } @Override public Map build() { Map result = _current; _current = null; return result; } @Override public MapBuilder put(Object key, Object value) { if (_checkDups) { if (_current.containsKey(key)) { // 14-Apr-2017, tatu: Note that choice of `IllegalArgumentException` is arbitrary // but not random: caller catches and re-packages it to give context throw new IllegalArgumentException("Duplicate key (key '"+key+"')"); } } _current.put(key, value); return this; } @Override public Map emptyMap() { if ((_mapType == null) && isEnabled(Feature.READ_ONLY)) { return Collections.emptyMap(); } return _map(4); } private final Map _map(int initialSize) { if (_mapType != null) { try { @SuppressWarnings("unchecked") Map m = (Map) _mapType.newInstance(); return m; } catch (Exception e) { Throwable t = e; while (t.getCause() != null) { t = t.getCause(); } throw new IllegalArgumentException("Failed to create an instance of " +_mapType.getName()+" ("+t.getClass().getName()+"): "+t.getMessage()); } } final boolean sort = isEnabled(Feature.PRESERVE_FIELD_ORDERING); if (isEnabled(Feature.USE_DEFERRED_MAPS)) { return new DeferredMap(sort, initialSize); } return sort ? new LinkedHashMap(initialSize) : new HashMap(initialSize); } } } MapReader.java000066400000000000000000000070071323200335100344220ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.jr.ob.JSONObjectException; /** * Reader for typed {@link java.util.Map} values. */ public class MapReader extends ValueReader { protected final Class _mapType; protected final ValueReader _valueReader; public MapReader(Class t, ValueReader vr) { // Some caveats: drop type if it's generic enough (aka "don't care") _mapType = (t == Map.class) ? null : t; _valueReader = vr; } @Override public Object readNext(JSONReader r, JsonParser p) throws IOException { if (p.nextToken() != JsonToken.START_OBJECT) { if (p.hasToken(JsonToken.VALUE_NULL)) { return null; } return JSONObjectException.from(p, "Unexpected token "+p.getCurrentToken()+"; should get START_OBJECT"); } MapBuilder b = r._mapBuilder(_mapType); String propName0 = p.nextFieldName(); if (propName0 == null) { if (p.hasToken(JsonToken.END_OBJECT)) { return b.emptyMap(); } throw _reportProblem(p); } Object value = _valueReader.readNext(r, p); String propName = p.nextFieldName(); if (propName == null) { if (p.hasToken(JsonToken.END_OBJECT)) { return b.singletonMap(propName0, value); } throw _reportProblem(p); } try { b = b.start().put(propName0, value); while (true) { b = b.put(propName, _valueReader.readNext(r, p)); propName = p.nextFieldName(); if (propName == null) { if (p.hasToken(JsonToken.END_OBJECT)) { return b.build(); } throw _reportProblem(p); } } } catch (IllegalArgumentException e) { throw JSONObjectException.from(p, e.getMessage()); } } @Override public Object read(JSONReader r, JsonParser p) throws IOException { MapBuilder b = r._mapBuilder(_mapType); String propName0 = p.nextFieldName(); if (propName0 == null) { if (p.hasToken(JsonToken.END_OBJECT)) { return b.emptyMap(); } throw _reportProblem(p); } Object value = _valueReader.readNext(r, p); String propName = p.nextFieldName(); if (propName == null) { if (p.hasToken(JsonToken.END_OBJECT)) { return b.singletonMap(propName0, value); } throw _reportProblem(p); } try { b = b.start().put(propName0, value); while (true) { b = b.put(propName, _valueReader.readNext(r, p)); propName = p.nextFieldName(); if (propName == null) { if (p.hasToken(JsonToken.END_OBJECT)) { return b.build(); } throw _reportProblem(p); } } } catch (IllegalArgumentException e) { throw JSONObjectException.from(p, e.getMessage()); } } protected JSONObjectException _reportProblem(JsonParser p) { return JSONObjectException.from(p, "Unexpected token "+p.getCurrentToken()+"; should get FIELD_NAME or END_OBJECT"); } } POJODefinition.java000066400000000000000000000170351323200335100353440ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.*; import java.util.concurrent.ConcurrentHashMap; /** * Definition of a single Bean-style Java class, without assumptions * on usage for serialization or deserialization, used as input * for constructing bean readers and writers. * * @since 2.8 */ public class POJODefinition { /** * Since there is just one global cache for type lookups, let's * limit the size to something quite modest: introspection is * not free, but holding onto information can cause issues * for larger systems */ private final static int MAX_CACHED = 100; private final static Prop[] NO_PROPS = new Prop[0]; protected final static ConcurrentHashMap, POJODefinition> DEFS = new ConcurrentHashMap, POJODefinition>(50, 0.75f, 4); protected final Class _type; protected final Prop[] _properties; public final Constructor defaultCtor; public final Constructor stringCtor; public final Constructor longCtor; /** * Constructors used for serialization use case */ public POJODefinition(Class type, Prop[] props, Constructor defaultCtor0, Constructor stringCtor0, Constructor longCtor0) { _type = type; _properties = props; defaultCtor = defaultCtor0; stringCtor = stringCtor0; longCtor = longCtor0; } /* /********************************************************************** /* Public API /********************************************************************** */ public static POJODefinition find(Class forType) { POJODefinition def = DEFS.get(forType); if (def == null) { def = _construct(forType); // Instead of trying to do LRU or just (which gets tricky with concurrent // access), let's just do "flush when full". In practice tends to work // quite well. if (DEFS.size() >= MAX_CACHED) { DEFS.clear(); } DEFS.putIfAbsent(forType, def); } return def; } public Prop[] properties() { return _properties; } /* /********************************************************************** /* Internal methods /********************************************************************** */ private static POJODefinition _construct(Class beanType) { Map propsByName = new TreeMap(); _introspect(beanType, propsByName); Constructor defaultCtor = null; Constructor stringCtor = null; Constructor longCtor = null; for (Constructor ctor : beanType.getDeclaredConstructors()) { Class[] argTypes = ctor.getParameterTypes(); if (argTypes.length == 0) { defaultCtor = ctor; } else if (argTypes.length == 1) { Class argType = argTypes[0]; if (argType == String.class) { stringCtor = ctor; } else if (argType == Long.class || argType == Long.TYPE) { longCtor = ctor; } else { continue; } } else { continue; } } Prop[] props; if (propsByName.isEmpty()) { props = NO_PROPS; } else { props = propsByName.values().toArray(new Prop[propsByName.size()]); } return new POJODefinition(beanType, props, defaultCtor, stringCtor, longCtor); } private static void _introspect(Class currType, Map props) { if (currType == null || currType == Object.class) { return; } // First, check base type _introspect(currType.getSuperclass(), props); // then public fields (since 2.8); may or may not be ultimately included // but at this point still possible for (Field f : currType.getDeclaredFields()) { if (!Modifier.isPublic(f.getModifiers()) || f.isEnumConstant() || f.isSynthetic()) { continue; } _propFrom(props, f.getName()).field = f; } // then get methods from within this class for (Method m : currType.getDeclaredMethods()) { final int flags = m.getModifiers(); // 13-Jun-2015, tatu: Skip synthetic, bridge methods altogether, for now // at least (add more complex handling only if absolutely necessary) if (Modifier.isStatic(flags) || m.isSynthetic() || m.isBridge()) { continue; } Class argTypes[] = m.getParameterTypes(); if (argTypes.length == 0) { // getter? // getters must be public to be used if (!Modifier.isPublic(flags)) { continue; } Class resultType = m.getReturnType(); if (resultType == Void.class) { continue; } String name = m.getName(); if (name.startsWith("get")) { if (name.length() > 3) { name = decap(name.substring(3)); _propFrom(props, name).getter = m; } } else if (name.startsWith("is")) { if (name.length() > 2) { // May or may not be used, but collect for now all the same: name = decap(name.substring(2)); _propFrom(props, name).isGetter = m; } } } else if (argTypes.length == 1) { // setter? // Non-public setters are fine if we can force access, don't yet check // let's also not bother about return type; setters that return value are fine String name = m.getName(); if (!name.startsWith("set") || name.length() == 3) { continue; } name = decap(name.substring(3)); _propFrom(props, name).setter = m; } } } private static Prop _propFrom(Map props, String name) { Prop prop = props.get(name); if (prop == null) { prop = new Prop(name); props.put(name, prop); } return prop; } private static String decap(String name) { char c = name.charAt(0); if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) && Character.isUpperCase(c)){ return name; } char chars[] = name.toCharArray(); chars[0] = Character.toLowerCase(c); return new String(chars); } /* /********************************************************************** /* Helper class for containing property definitions /********************************************************************** */ public static final class Prop { public final String name; public Method setter, getter, isGetter; public Field field; public Prop(String name) { this.name = name; } public boolean hasSetter() { return (setter != null) || (field != null); } } } SimpleValueReader.java000066400000000000000000000137461323200335100361420ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import static com.fasterxml.jackson.jr.ob.impl.TypeDetector.*; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URL; import java.util.*; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.jr.ob.JSONObjectException; /** * {@link ValueReader} used for simple scalar types and related. */ public class SimpleValueReader extends ValueReader { protected final int _typeId; protected final Class _rawType; public SimpleValueReader(int typeId, Class raw) { _typeId = typeId; _rawType = raw; } @Override public Object readNext(JSONReader reader, JsonParser p) throws IOException { // NOTE: only cases where we can optimize switch (_typeId) { // Textual types, related: case SER_STRING: case SER_CHARACTER_SEQUENCE: return _nextString(p); case SER_CHAR_ARRAY: String str = _nextString(p); return (str == null) ? null : str.toCharArray(); // Number types: case SER_NUMBER_SHORT: // fall through return Short.valueOf((short) _nextInt(p)); case SER_NUMBER_INTEGER: return Integer.valueOf(_nextInt(p)); case SER_NUMBER_LONG: return Long.valueOf(_nextLong(p)); // Other scalar types: case SER_BOOLEAN: { Boolean b = p.nextBooleanValue(); if (b != null) { return b; } return p.getValueAsBoolean(); } } p.nextToken(); return read(reader, p); } @Override public Object read(JSONReader reader, JsonParser p) throws IOException { switch (_typeId) { case SER_MAP: case SER_LIST: case SER_COLLECTION: case SER_OBJECT_ARRAY: // should never get here: we have dedicated readers break; case SER_INT_ARRAY: return _readIntArray(p); case SER_TREE_NODE: return reader._treeCodec().readTree(p); // Textual types, related: case SER_STRING: case SER_CHARACTER_SEQUENCE: return p.getValueAsString(); case SER_CHAR_ARRAY: return p.getValueAsString().toCharArray(); case SER_BYTE_ARRAY: return _readBinary(p); // Number types: case SER_NUMBER_FLOAT: // fall through return Float.valueOf((float) p.getValueAsDouble()); case SER_NUMBER_DOUBLE: return p.getValueAsDouble(); case SER_NUMBER_BYTE: // fall through return (byte) p.getValueAsInt(); case SER_NUMBER_SHORT: // fall through return (short) p.getValueAsInt(); case SER_NUMBER_INTEGER: return p.getValueAsInt(); case SER_NUMBER_LONG: return p.getValueAsLong(); case SER_NUMBER_BIG_DECIMAL: return p.getDecimalValue(); case SER_NUMBER_BIG_INTEGER: return p.getBigIntegerValue(); // Other scalar types: case SER_BOOLEAN: return p.getValueAsBoolean(); case SER_CHAR: { String str = p.getValueAsString(); return (str == null || str.isEmpty()) ? ' ' : str.charAt(0); } case SER_CALENDAR: { long l = _fetchLong(p); Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(l); return cal; } case SER_DATE: return new Date(_fetchLong(p)); case SER_CLASS: { String v = p.getValueAsString(); try { return Class.forName(v); } catch (Exception e) { throw new JSONObjectException("Failed to bind java.lang.Class from value '"+v+"'"); } } case SER_FILE: return new File(p.getValueAsString()); case SER_UUID: return UUID.fromString(p.getValueAsString()); case SER_URL: return new URL(p.getValueAsString()); case SER_URI: return URI.create(p.getValueAsString()); default: // types that shouldn't get here //case SER_ENUM: } throw JSONObjectException.from(p, "Can not create a "+_rawType.getName()+" instance out of "+_tokenDesc(p)); } /* /********************************************************************** /* Read methods for scalars /********************************************************************** */ protected byte[] _readBinary(JsonParser p) throws IOException { return p.getBinaryValue(); } protected int[] _readIntArray(JsonParser p) throws IOException { // !!! TODO throw new JSONObjectException("Reading of int[] not yet implemented"); } protected long _fetchLong(JsonParser p) throws IOException { JsonToken t = p.getCurrentToken(); if (t == JsonToken.VALUE_NUMBER_INT) { return p.getLongValue(); } throw JSONObjectException.from(p, "Can not get long numeric value from JSON (to construct " +_rawType.getName()+") from "+_tokenDesc(p, t)); } private final String _nextString(JsonParser p) throws IOException { String str = p.nextTextValue(); return (str == null) ? p.getValueAsString() : str; } private final int _nextInt(JsonParser p) throws IOException { int i = p.nextIntValue(-2); if (i != -2) { return i; } return p.getValueAsInt(); } private final long _nextLong(JsonParser p) throws IOException { long l = p.nextLongValue(-2L); if (l != -2L) { return l; } return p.getValueAsLong(); } } TypeDetector.java000066400000000000000000000612741323200335100352030ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import java.io.File; import java.lang.reflect.*; import java.math.BigDecimal; import java.math.BigInteger; import java.net.URI; import java.net.URL; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import com.fasterxml.jackson.core.TreeNode; import com.fasterxml.jackson.jr.ob.JSON; import com.fasterxml.jackson.jr.type.ResolvedType; import com.fasterxml.jackson.jr.type.TypeBindings; import com.fasterxml.jackson.jr.type.TypeResolver; /** * Helper object used for efficient detection of type information * relevant to our conversion needs when writing out Java Objects * as JSON. *

* Note that usage pattern is such that a single "root" instance is kept * by each {@link com.fasterxml.jackson.jr.ob.JSON} instance; and * an actual per-operation instance must be constructed by calling * {@link #perOperationInstance}: reason for this is that instances * use simple caching to handle the common case of repeating types * within JSON Arrays. */ public class TypeDetector { protected final BeanPropertyWriter[] NO_PROPS_FOR_WRITE = new BeanPropertyWriter[0]; /** * While we should be able to cache all types in the active working set, * we should also avoid potential unbounded retention, since there is * generally just one big `TypeDetector` instances per JVM (or at least * ClassLoader). */ protected final static int MAX_CACHED_READERS = 500; /* /********************************************************************** /* Value constants for serialization /********************************************************************** */ /* FAQ: Why ints? Why not Enums?!? Glad you asked: one reasons is class * size reduction: javac creates annonymous inner class for each switch * on enum (per referring type and enum: can combine multiple). So by * not using enunms we try to minimize code foot print. * But this is ONLY done because Value Type constants are NOT part of * public API: if they were, size savings wouldn't make sense. * * One more note: negative values are used for dynamically introspected * Beans. */ /** * Type not yet resolved */ public final static int SER_UNKNOWN = 0; /** * All kinds of {@link java.util.Map}s. */ public final static int SER_MAP = 1; /** * All kinds of {@link java.util.List}s. */ public final static int SER_LIST = 2; /** * All kinds of {@link java.util.Collection}s other than {@link java.util.List}s */ public final static int SER_COLLECTION = 3; /** * Arrays of non-primitive types */ public final static int SER_OBJECT_ARRAY = 4; public final static int SER_INT_ARRAY = 5; public final static int SER_LONG_ARRAY = 6; public final static int SER_BOOLEAN_ARRAY = 7; /** * An implementation of {@link com.fasterxml.jackson.core.TreeNode} */ public final static int SER_TREE_NODE = 8; // // // String(-like) types public final static int SER_STRING = 9; public final static int SER_CHARACTER_SEQUENCE = 10; public final static int SER_CHAR_ARRAY = 11; public final static int SER_BYTE_ARRAY = 12; // // // Numbers public final static int SER_NUMBER_BYTE = 13; public final static int SER_NUMBER_SHORT = 14; public final static int SER_NUMBER_INTEGER = 15; public final static int SER_NUMBER_LONG = 16; public final static int SER_NUMBER_FLOAT = 17; public final static int SER_NUMBER_DOUBLE = 18; public final static int SER_NUMBER_BIG_INTEGER = 19; public final static int SER_NUMBER_BIG_DECIMAL = 20; // // // Other specific scalar types public final static int SER_BOOLEAN = 21; public final static int SER_CHAR = 22; public final static int SER_ENUM = 23; public final static int SER_DATE = 24; public final static int SER_CALENDAR = 25; public final static int SER_CLASS = 26; public final static int SER_FILE = 27; public final static int SER_UUID = 28; public final static int SER_URL = 29; public final static int SER_URI = 30; // // // Iterate-able types /** * Anything that implements {@link java.lang.Iterable}, but not * {@link java.util.Collection}. */ public final static int SER_ITERABLE = 31; /* /********************************************************************** /* Other constants /********************************************************************** */ protected final static int CACHE_FLAGS = JSON.Feature.cacheBreakers(); /* /********************************************************************** /* Helper objects, serialization /********************************************************************** */ /** * Mapping from classes to resolved type constants or indexes, to use * for serialization. */ protected final ConcurrentHashMap _knownSerTypes; protected final CopyOnWriteArrayList _knownWriters; /* /********************************************************************** /* Helper objects, deserialization /********************************************************************** */ /** * For generic containers (Collections, Maps, arrays), we may need * this guy. */ protected final TypeResolver _typeResolver; /** * Set of {@link ValueReader}s that we have resolved */ protected final ConcurrentHashMap _knownReaders; /** * During resolution, some readers may be in-progress, but need to be * linked: for example, with cyclic type references. */ protected Map _incompleteReaders; protected final Object _readerLock; /* /********************************************************************** /* Instance state /********************************************************************** */ /** * Reusable lookup key; only used by per-thread instances. */ protected ClassKey _key; protected Class _prevClass; protected int _prevType; protected int _features; /* /********************************************************************** /* Construction /********************************************************************** */ /** * Constructor for the blueprint instance */ protected TypeDetector(int features) { _features = features; _knownSerTypes = new ConcurrentHashMap(50, 0.75f, 4); _knownWriters = new CopyOnWriteArrayList(); _knownReaders = new ConcurrentHashMap(50, 0.75f, 4); _typeResolver = new TypeResolver(); _readerLock = new Object(); } protected TypeDetector(TypeDetector base, int features) { _features = features; _knownSerTypes = base._knownSerTypes; _knownWriters = base._knownWriters; _knownReaders = base._knownReaders; _typeResolver = base._typeResolver; _readerLock = base._readerLock; } public final static TypeDetector blueprint(int features) { return new TypeDetector(features & CACHE_FLAGS); } public TypeDetector perOperationInstance(int features) { return new TypeDetector(this, features & CACHE_FLAGS); } /* /********************************************************************** /* Methods for ser and deser /********************************************************************** */ protected POJODefinition resolvePOJODefinition(Class raw) { try { return POJODefinition.find(raw); } catch (Exception e) { throw new IllegalArgumentException(String.format ("Failed to introspect ClassDefinition for type '%s': %s", raw.getName(), e.getMessage()), e); } } protected int _findSimple(Class raw, boolean forSer) { if (raw == String.class) { return SER_STRING; } if (raw.isArray()) { Class elemType = raw.getComponentType(); if (elemType.isPrimitive()) { if (raw == byte[].class) { return SER_BYTE_ARRAY; } if (raw == char[].class) { return SER_CHAR_ARRAY; } if (raw == int[].class) { return SER_INT_ARRAY; } if (raw == long[].class) { return SER_LONG_ARRAY; } if (raw == boolean[].class) { return SER_BOOLEAN_ARRAY; } // Hmmh. Could support all types; add as/when needed return SER_UNKNOWN; } return SER_OBJECT_ARRAY; } if (raw.isPrimitive()) { if (raw == Boolean.TYPE) return SER_BOOLEAN; if (raw == Integer.TYPE) return SER_NUMBER_INTEGER; if (raw == Long.TYPE) return SER_NUMBER_LONG; if (raw == Byte.TYPE) return SER_NUMBER_BYTE; if (raw == Short.TYPE) return SER_NUMBER_SHORT; if (raw == Double.TYPE) return SER_NUMBER_DOUBLE; if (raw == Float.TYPE) return SER_NUMBER_FLOAT; if (raw == Character.TYPE) return SER_CHAR; throw new IllegalArgumentException("Unrecognized primitive type: "+raw.getName()); } if (raw == Boolean.class) { return SER_BOOLEAN; } if (Number.class.isAssignableFrom(raw)) { if (raw == Integer.class) return SER_NUMBER_INTEGER; if (raw == Long.class) return SER_NUMBER_LONG; if (raw == Byte.class) return SER_NUMBER_BYTE; if (raw == Short.class) return SER_NUMBER_SHORT; if (raw == Double.class) return SER_NUMBER_DOUBLE; if (raw == Float.class) return SER_NUMBER_FLOAT; if (raw == BigDecimal.class) return SER_NUMBER_BIG_DECIMAL; if (raw == BigInteger.class) { return SER_NUMBER_BIG_INTEGER; } // What numeric type is this? Could consider "string-like" but... return SER_UNKNOWN; } if (raw == Character.class) { return SER_CHAR; } if (raw.isEnum()) { return SER_ENUM; } if (Map.class.isAssignableFrom(raw)) { return SER_MAP; } if (Collection.class.isAssignableFrom(raw)) { if (List.class.isAssignableFrom(raw)) { // One more thing: here we assume LIST means efficient random access if (RandomAccess.class.isAssignableFrom(raw)) { return SER_LIST; } // and if not, consider "only" a collection } return SER_COLLECTION; } if (TreeNode.class.isAssignableFrom(raw)) { // should we require more accurate type for deser? return SER_TREE_NODE; } // Misc String-like types if (Calendar.class.isAssignableFrom(raw)) { return SER_CALENDAR; } if (raw == Class.class) { return SER_CLASS; } if (Date.class.isAssignableFrom(raw)) { return SER_DATE; } if (File.class.isAssignableFrom(raw)) { return SER_FILE; } if (URL.class.isAssignableFrom(raw)) { return SER_URL; } if (URI.class.isAssignableFrom(raw)) { return SER_URI; } if (UUID.class.isAssignableFrom(raw)) { return SER_UUID; } /* May or may not help with deser, but recognized nonetheless; * on assumption that Beans should rarely implement `CharSequence` */ if (CharSequence.class.isAssignableFrom(raw)) { return SER_CHARACTER_SEQUENCE; } /* `Iterable` can be added on all kinds of things, and it won't * help at all with deserialization; hence only use for serialization. */ if (forSer && Iterable.class.isAssignableFrom(raw)) { return SER_ITERABLE; } // Ok. I give up, no idea! return SER_UNKNOWN; } /* /********************************************************************** /* Methods for serialization /********************************************************************** */ public BeanPropertyWriter[] getPropertyWriters(int index) { // for simplicity, let's allow caller to pass negative id as is if (index < 0) { index = -(index+1); } return _knownWriters.get(index); } /** * The main lookup method used to find type identifier for * given raw class; including Bean types (if allowed). */ public final int findSerializationType(Class raw) { if (raw == _prevClass) { return _prevType; } if (raw == String.class) { return SER_STRING; } ClassKey k = (_key == null) ? new ClassKey(raw, _features) : _key.with(raw, _features); int type; Integer I = _knownSerTypes.get(k); if (I == null) { type = _findPOJOSerializationType(raw); _knownSerTypes.put(new ClassKey(raw, _features), Integer.valueOf(type)); } else { type = I.intValue(); } _prevType = type; _prevClass = raw; return type; } protected int _findPOJOSerializationType(Class raw) { int type = _findSimple(raw, true); if (type == SER_UNKNOWN) { if (JSON.Feature.HANDLE_JAVA_BEANS.isEnabled(_features)) { POJODefinition cd = resolvePOJODefinition(raw); BeanPropertyWriter[] props = resolveBeanForSer(raw, cd); // Due to concurrent access, possible that someone might have added it synchronized (_knownWriters) { // Important: do NOT try to reuse shared instance; caller needs it ClassKey k = new ClassKey(raw, _features); Integer I = _knownSerTypes.get(k); // if it was already concurrently added, we'll just discard this copy, return earlier if (I != null) { return I.intValue(); } // otherwise add at the end, use -(index+1) as id _knownWriters.add(props); int typeId = -_knownWriters.size(); _knownSerTypes.put(k, Integer.valueOf(typeId)); return typeId; } } } return type; } protected BeanPropertyWriter[] resolveBeanForSer(Class raw, POJODefinition classDef) { POJODefinition.Prop[] rawProps = classDef.properties(); final int len = rawProps.length; List props = new ArrayList(len); final boolean includeReadOnly = JSON.Feature.WRITE_READONLY_BEAN_PROPERTIES.isEnabled(_features); final boolean forceAccess = JSON.Feature.FORCE_REFLECTION_ACCESS.isEnabled(_features); final boolean useFields = JSON.Feature.USE_FIELDS.isEnabled(_features); for (int i = 0; i < len; ++i) { POJODefinition.Prop rawProp = rawProps[i]; Method m = rawProp.getter; if (m == null) { if (JSON.Feature.USE_IS_GETTERS.isEnabled(_features)) { m = rawProp.isGetter; } } Field f = useFields ? rawProp.field : null; // But if neither regular nor is-getter, move on if ((m == null) && (f == null)) { continue; } // also: if setter is required to match, skip if none if (!includeReadOnly && !rawProp.hasSetter()) { continue; } Class type; if (m != null) { type = m.getReturnType(); if (forceAccess) { m.setAccessible(true); } } else { type = f.getType(); if (forceAccess) { f.setAccessible(true); } } int typeId = _findSimple(type, true); props.add(new BeanPropertyWriter(typeId, rawProp.name, rawProp.field, m)); } int plen = props.size(); BeanPropertyWriter[] propArray = (plen == 0) ? NO_PROPS_FOR_WRITE : props.toArray(new BeanPropertyWriter[plen]); return propArray; } /* /********************************************************************** /* Methods for deserialization; simple factory methods /********************************************************************** */ public ValueReader enumReader(Class enumType) { Object[] enums = enumType.getEnumConstants(); Map byName = new HashMap(); for (Object e : enums) { byName.put(e.toString(), e); } return new EnumReader(enums, byName); } protected ValueReader collectionReader(Class contextType, Type collectionType) { ResolvedType t = _typeResolver.resolve(bindings(contextType), collectionType); List params = t.typeParametersFor(Collection.class); return collectionReader(t.erasedType(), params.get(0)); } protected ValueReader collectionReader(Class collectionType, ResolvedType valueType) { Class raw = valueType.erasedType(); if (Collection.class.isAssignableFrom(raw)) { List params = valueType.typeParametersFor(Collection.class); return collectionReader(raw, params.get(0)); } if (Map.class.isAssignableFrom(raw)) { List params = valueType.typeParametersFor(Map.class); return mapReader(raw, params.get(1)); } return new CollectionReader(collectionType, createReader(null, raw, raw)); } protected ValueReader mapReader(Class contextType, Type mapType) { ResolvedType t = _typeResolver.resolve(bindings(contextType), mapType); List params = t.typeParametersFor(Map.class); return mapReader(t.erasedType(), params.get(1)); } protected ValueReader mapReader(Class mapType, ResolvedType valueType) { Class raw = valueType.erasedType(); if (Collection.class.isAssignableFrom(raw)) { List params = valueType.typeParametersFor(Collection.class); return collectionReader(raw, params.get(0)); } if (Map.class.isAssignableFrom(raw)) { List params = valueType.typeParametersFor(Map.class); return mapReader(raw, params.get(1)); } return new MapReader(mapType, createReader(null, raw, raw)); } /* /********************************************************************** /* Methods for deserialization; other /********************************************************************** */ /** * Method used during deserialization to find handler for given * non-generic type. */ public ValueReader findReader(Class raw) { ClassKey k = (_key == null) ? new ClassKey(raw, _features) : _key.with(raw, _features); ValueReader vr = _knownReaders.get(k); if (vr != null) { return vr; } vr = createReader(null, raw, raw); // 15-Jun-2016, tatu: Let's limit maximum number of readers to prevent // unbounded memory retention (at least wrt readers) if (_knownReaders.size() >= MAX_CACHED_READERS) { _knownReaders.clear(); } _knownReaders.putIfAbsent(new ClassKey(raw, _features), vr); return vr; } protected ValueReader createReader(Class contextType, Class type, Type genericType) { if (type == Object.class) { return AnyReader.std; } if (type.isArray()) { Class elemType = type.getComponentType(); if (!elemType.isPrimitive()) { return new ArrayReader(elemType, createReader(contextType, elemType, elemType)); } int typeId = _findSimple(type, false); if (typeId > 0) { return new SimpleValueReader(typeId, type); } throw new IllegalArgumentException("Deserialization of "+type.getName()+" not (yet) supported"); } if (type.isEnum()) { return enumReader(type); } if (Collection.class.isAssignableFrom(type)) { return collectionReader(contextType, genericType); } if (Map.class.isAssignableFrom(type)) { return mapReader(contextType, genericType); } int typeId = _findSimple(type, false); if (typeId > 0) { return new SimpleValueReader(typeId, type); } // Beans! final ClassKey key = new ClassKey(type, _features); synchronized (_readerLock) { if (_incompleteReaders == null) { _incompleteReaders = new HashMap(); } else { // perhaps it has already been resolved? ValueReader vr = _incompleteReaders.get(key); if (vr != null) { return vr; } } BeanReader def = _resolveBeanForDeser(type); try { _incompleteReaders.put(key, def); for (Map.Entry entry : def.propertiesByName().entrySet()) { BeanPropertyReader prop = entry.getValue(); entry.setValue(prop.withReader(createReader(contextType, prop.rawSetterType(), prop.genericSetterType()))); } } finally { _incompleteReaders.remove(key); } return def; } } protected BeanReader _resolveBeanForDeser(Class raw) { final POJODefinition pojoDef = resolvePOJODefinition(raw); Constructor defaultCtor = pojoDef.defaultCtor; Constructor stringCtor = pojoDef.stringCtor; Constructor longCtor = pojoDef.longCtor; final boolean forceAccess = JSON.Feature.FORCE_REFLECTION_ACCESS.isEnabled(_features); if (forceAccess) { if (defaultCtor != null) { defaultCtor.setAccessible(true); } if (stringCtor != null) { stringCtor.setAccessible(true); } if (longCtor != null) { longCtor.setAccessible(true); } } final POJODefinition.Prop[] rawProps = pojoDef.properties(); final int len = rawProps.length; final Map propMap; if (len == 0) { propMap = Collections.emptyMap(); } else { propMap = new HashMap(); final boolean useFields = JSON.Feature.USE_FIELDS.isEnabled(_features); for (int i = 0; i < len; ++i) { POJODefinition.Prop rawProp = rawProps[i]; Method m = rawProp.setter; Field f = useFields ? rawProp.field : null; if (m != null) { if (forceAccess) { m.setAccessible(true); } else if (!Modifier.isPublic(m.getModifiers())) { // access to non-public setters must be forced to be usable: m = null; } } // if no setter, field would do as well if (m == null) { if (f == null) { continue; } // fields should always be public, but let's just double-check if (forceAccess) { f.setAccessible(true); } else if (!Modifier.isPublic(f.getModifiers())) { continue; } } propMap.put(rawProp.name, new BeanPropertyReader(rawProp.name, f, m)); } } return new BeanReader(raw, propMap, defaultCtor, stringCtor, longCtor); } private TypeBindings bindings(Class ctxt) { if (ctxt == null) { return TypeBindings.emptyBindings(); } return TypeBindings.create(ctxt, (ResolvedType[]) null); } } ValueReader.java000066400000000000000000000036061323200335100347620ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; /** * Helper class used when reading values of complex types other * than Beans. *

* Note that ugly "chameleon" style operation here is used to avoid * creating multiple separate classes, which in turn is done to minimize * size of resulting jars. */ public abstract class ValueReader { /* /********************************************************************** /* Basic API /********************************************************************** */ public abstract Object read(JSONReader reader, JsonParser p) throws IOException; public abstract Object readNext(JSONReader reader, JsonParser p) throws IOException; /* /********************************************************************** /* Helper methods for sub-classes /********************************************************************** */ protected String _tokenDesc(JsonParser p) throws IOException { return _tokenDesc(p, p.getCurrentToken()); } protected static String _tokenDesc(JsonParser p, JsonToken t) throws IOException { if (t == null) { return "NULL"; } switch (t) { case FIELD_NAME: return "JSON Field name '"+p.getCurrentName()+"'"; case START_ARRAY: return "JSON Array"; case START_OBJECT: return "JSON Object"; case VALUE_FALSE: return "'false'"; case VALUE_NULL: return "'null'"; case VALUE_NUMBER_FLOAT: case VALUE_NUMBER_INT: return "JSON Number"; case VALUE_STRING: return "JSON String"; case VALUE_TRUE: return "'true'"; default: return t.toString(); } } } jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/type/000077500000000000000000000000001323200335100314125ustar00rootroot00000000000000ClassStack.java000066400000000000000000000021111323200335100342240ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/typepackage com.fasterxml.jackson.jr.type; import java.util.ArrayList; final class ClassStack { private final ClassStack _p; private final Class _curr; private ArrayList _selfRefs; public ClassStack(Class rootType) { this(null, rootType); } private ClassStack(ClassStack parent, Class curr) { _p = parent; _curr = curr; } public ClassStack child(Class cls) { return new ClassStack(this, cls); } public void addSelfReference(RecursiveType ref) { if (_selfRefs == null) { _selfRefs = new ArrayList(); } _selfRefs.add(ref); } public void resolveSelfReferences(ResolvedType resolved) { if (_selfRefs != null) { for (RecursiveType ref : _selfRefs) { ref.setReference(resolved); } } } public ClassStack find(Class cls) { if (_curr == cls) return this; if (_p != null) { return _p.find(cls); } return null; } }RecursiveType.java000066400000000000000000000011251323200335100350060ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/typepackage com.fasterxml.jackson.jr.type; public class RecursiveType extends ResolvedType { private static final long serialVersionUID = 1L; protected ResolvedType _referencedType; public RecursiveType(Class erased, TypeBindings bindings) { super(erased, bindings); } void setReference(ResolvedType ref) { _referencedType = ref; } public ResolvedType selfRefType() { return _referencedType; } @Override public boolean equals(Object o) { // shouldn't really ever match, even if resolved to same thing, should it? return (this == o); } } ResolvedType.java000066400000000000000000000137311323200335100346300ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/typepackage com.fasterxml.jackson.jr.type; import java.io.Serializable; import java.util.*; public class ResolvedType implements java.lang.reflect.Type, Serializable { private static final long serialVersionUID = 1L; public final static ResolvedType[] NO_TYPES = new ResolvedType[0]; protected final static int T_ARRAY = 1; protected final static int T_INTERFACE = 2; protected final static int T_PRIMITIVE = 3; protected final static int T_RECURSIVE = 4; protected final static int T_REGULAR = 5; protected final int _kind; protected final Class _erasedType; protected final TypeBindings _bindings; // interfaces implemented protected final ResolvedType[] _interfaces; // for arrays, type of element contained protected final ResolvedType _elemType; // for "regular" class types, super-class protected final ResolvedType _super; // for primitives protected ResolvedType(Class cls) { this(T_PRIMITIVE, cls, null, null, null, null); } // for recursive types protected ResolvedType(Class cls, TypeBindings bindings) { this(T_PRIMITIVE, cls, null, null, null, null); } // for Array type protected ResolvedType(Class cls, TypeBindings bindings, ResolvedType elemType) { this(T_ARRAY, cls, null, bindings, null, elemType); } // for Interfaces protected ResolvedType(Class cls, TypeBindings bindings, ResolvedType[] ifaces) { this(T_INTERFACE, cls, null, bindings, ifaces, null); } // for "Regular" classes protected ResolvedType(Class cls, ResolvedType sup, TypeBindings bindings, ResolvedType[] ifaces) { this(T_REGULAR, cls, sup, bindings, ifaces, null); } private ResolvedType(int k, Class cls, ResolvedType sup, TypeBindings bindings, ResolvedType[] ifs, ResolvedType elemType) { _kind = k; _erasedType = cls; _super = sup; _bindings = (bindings == null) ? TypeBindings.emptyBindings() : bindings; _interfaces = ifs; _elemType = elemType; } public Class erasedType() { return _erasedType; } public ResolvedType elementType() { return _elemType; } public ResolvedType parentType() { return _super; } public boolean isArray() { return _kind == T_ARRAY; } public final List implInterfaces() { if (_interfaces == null || _interfaces.length == 0) { return Collections.emptyList(); } return Arrays.asList(_interfaces); } public List typeParams() { return _bindings.getTypeParameters(); } public TypeBindings typeBindings() { return _bindings; } /** * Method that will try to find type parameterization this type * has for specified super type * * @return List of type parameters for specified supertype (which may * be empty, if supertype is not a parametric type); null if specified * type is not a super type of this type */ public List typeParametersFor(Class erasedSupertype) { ResolvedType type = findSupertype(erasedSupertype); if (type != null) { return type.typeParams(); } return null; } /** * Method for finding super type of this type that has specified type * erased signature. If supertype is an interface which is implemented * using multiple inheritance paths, preference is given to interfaces * implemented "highest up the stack" (directly implemented interfaces * over interfaces superclass implements). */ public ResolvedType findSupertype(Class erasedSupertype) { if (erasedSupertype == _erasedType) { return this; } // Check super interfaces first: if (erasedSupertype.isInterface()) { for (ResolvedType it : implInterfaces()) { ResolvedType type = it.findSupertype(erasedSupertype); if (type != null) { return type; } } } // and if not found, super class and its supertypes ResolvedType pc = parentType(); if (pc != null) { ResolvedType type = pc.findSupertype(erasedSupertype); if (type != null) { return type; } } // nope; doesn't look like we extend or implement super type in question return null; } public String getDesc() { StringBuilder sb = new StringBuilder(); return appendDesc(sb).toString(); } public StringBuilder appendDesc(StringBuilder sb) { switch (_kind) { case T_PRIMITIVE: return sb.append(_erasedType.getName()); case T_ARRAY: return _elemType.appendDesc(sb).append("[]"); } return _appendClassDesc(sb); } @Override public String toString() { return getDesc(); } @Override public int hashCode() { return _erasedType.getName().hashCode() + _bindings.hashCode(); } @Override public boolean equals(Object o) { if (o == this) return true; // sub-types must be same: if (o == null || o.getClass() != getClass()) return false; // Should be possible to actually implement here... ResolvedType other = (ResolvedType) o; if (other._erasedType != _erasedType) { return false; } // and type bindings must match as well return _bindings.equals(other._bindings); } protected StringBuilder _appendClassDesc(StringBuilder sb) { sb.append(_erasedType.getName()); int count = _bindings.size(); if (count > 0) { sb.append('<'); for (int i = 0; i < count; ++i) { if (i > 0) { sb.append(','); } sb = _bindings.getBoundType(i).appendDesc(sb); } sb.append('>'); } return sb; } } TypeBindings.java000066400000000000000000000127111323200335100345770ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/typepackage com.fasterxml.jackson.jr.type; import java.lang.reflect.TypeVariable; import java.util.*; /** * Helper class used for storing binding of local type variables to * matching resolved types, in context of a single class. */ public final class TypeBindings implements java.io.Serializable { private static final long serialVersionUID = 1L; private final static String[] NO_STRINGS = new String[0]; private final static ResolvedType[] NO_TYPES = new ResolvedType[0]; private final static TypeBindings EMPTY = new TypeBindings(NO_STRINGS, NO_TYPES, null); private final String[] _names; private final ResolvedType[] _types; /** * Names of potentially unresolved type variables. Needs to be separate from * actual names since these are only used during resolution of possible * self-references. * * @since 2.7 */ private final String[] _unboundVariables; private final int _hashCode; private TypeBindings(String[] names, ResolvedType[] types, String[] uvars) { _names = (names == null) ? NO_STRINGS : names; _types = (types == null) ? NO_TYPES : types; int h = 1; for (int i = 0, len = _types.length; i < len; ++i) { h += _types[i].hashCode(); } _unboundVariables = uvars; _hashCode = h; } public static TypeBindings emptyBindings() { return EMPTY; } public static TypeBindings create(Class erasedType, List typeList) { ResolvedType[] types = (typeList == null || typeList.isEmpty()) ? NO_TYPES : typeList.toArray(new ResolvedType[typeList.size()]); return create(erasedType, types); } public static TypeBindings create(Class erasedType, ResolvedType[] types) { if (types == null) { types = NO_TYPES; } TypeVariable[] vars = erasedType.getTypeParameters(); String[] names; if (vars.length == 0) { names = NO_STRINGS; } else { int len = vars.length; names = new String[len]; for (int i = 0; i < len; ++i) { names[i] = vars[i].getName(); } } return new TypeBindings(names, types, null); } /** * Method for creating an instance that has same bindings as this object, * plus an indicator for additional type variable that may be unbound within * this context; this is needed to resolve recursive self-references. */ public TypeBindings withUnboundVariable(String name) { int len = (_unboundVariables == null) ? 0 : _unboundVariables.length; String[] names = (len == 0) ? new String[1] : Arrays.copyOf(_unboundVariables, len+1); names[len] = name; return new TypeBindings(_names, _types, names); } /* /********************************************************************** /* Accessors /********************************************************************** */ public ResolvedType findBoundType(String name) { for (int i = 0, len = _names.length; i < len; ++i) { if (name.equals(_names[i])) { return _types[i]; } } return null; } public boolean isEmpty() { return (_types.length == 0); } public int size() { return _types.length; } public String getBoundName(int index) { if (index < 0 || index >= _names.length) { return null; } return _names[index]; } public ResolvedType getBoundType(int index) { if (index < 0 || index >= _types.length) { return null; } return _types[index]; } public List getTypeParameters() { if (_types.length == 0) { return Collections.emptyList(); } return Arrays.asList(_types); } /** * @since 2.3 */ public boolean hasUnbound(String name) { if (_unboundVariables != null) { for (int i = _unboundVariables.length; --i >= 0; ) { if (name.equals(_unboundVariables[i])) { return true; } } } return false; } /* /********************************************************************** /* Standard methods /********************************************************************** */ @Override public String toString() { if (_types.length == 0) { return ""; } StringBuilder sb = new StringBuilder(); sb.append('<'); for (int i = 0, len = _types.length; i < len; ++i) { if (i > 0) { sb.append(','); } sb = _types[i].appendDesc(sb); } sb.append('>'); return sb.toString(); } @Override public int hashCode() { return _hashCode; } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null || o.getClass() != getClass()) return false; TypeBindings other = (TypeBindings) o; int len = _types.length; if (len != other.size()) { return false; } ResolvedType[] otherTypes = other._types; for (int i = 0; i < len; ++i) { if (!otherTypes[i].equals(_types[i])) { return false; } } return true; } protected ResolvedType[] typeParameterArray() { return _types; } } TypeResolver.java000066400000000000000000000205521323200335100346450ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/java/com/fasterxml/jackson/jr/typepackage com.fasterxml.jackson.jr.type; import java.io.Serializable; import java.lang.reflect.*; import java.util.*; import com.fasterxml.jackson.jr.ob.impl.ClassKey; /** * Object that is used for resolving generic type information of a class * so that it is accessible using simple API. Resolved types are also starting * point for accessing resolved (generics aware) return and argument types * of class members (methods, fields, constructors). *

* Note that resolver instances are stateful in that resolvers cache resolved * types for efficiency. Since this is internal state and not directly visible * to callers, access to state is fully synchronized so that access from * multiple threads is safe. */ public class TypeResolver implements Serializable { private static final long serialVersionUID = 1L; private final static ResolvedType[] NO_TYPES = new ResolvedType[0]; // // Pre-created instances private final static ResolvedType TYPE_OBJECT = new ResolvedType(Object.class, /* no super-class*/ null, null, null); private final static HashMap _primitives; static { _primitives = new HashMap(16); ResolvedType[] all = new ResolvedType[] { new ResolvedType(Boolean.TYPE), new ResolvedType(Byte.TYPE), new ResolvedType(Short.TYPE), new ResolvedType(Character.TYPE), new ResolvedType(Integer.TYPE), new ResolvedType(Long.TYPE), new ResolvedType(Float.TYPE), new ResolvedType(Double.TYPE) }; for (ResolvedType type : all) { _primitives.put(new ClassKey(type.erasedType(), 0), type); } _primitives.put(new ClassKey(Void.TYPE, 0), new ResolvedType(Void.TYPE)); _primitives.put(new ClassKey(Object.class, 0), TYPE_OBJECT); } // // Caching protected final transient Map _cache = new HashMap(16, 0.8f); public TypeResolver() { } // To make sure we have empty but valid TypeResolver do this: protected Object readResolve() { if (_cache == null) { return new TypeResolver(); } return this; } /** * Factory method for resolving specified Java {@link java.lang.reflect.Type}, given * {@link TypeBindings} needed to resolve any type variables. *

* Use of this method is discouraged (use if and only if you really know what you * are doing!); but if used, type bindings passed should come from {@link ResolvedType} * instance of declaring class (or interface). */ public ResolvedType resolve(TypeBindings typeBindings, Type jdkType) { return _fromAny(null, jdkType, typeBindings); } private ResolvedType _fromAny(ClassStack context, Type mainType, TypeBindings typeBindings) { if (mainType instanceof Class) { return _fromClass(context, (Class) mainType, typeBindings); } if (mainType instanceof ResolvedType) { return (ResolvedType) mainType; } if (mainType instanceof ParameterizedType) { return _fromParamType(context, (ParameterizedType) mainType, typeBindings); } if (mainType instanceof GenericArrayType) { ResolvedType elementType = _fromAny(context, ((GenericArrayType) mainType).getGenericComponentType(), typeBindings); // Figuring out raw class for generic array is actually bit tricky... Object emptyArray = Array.newInstance(elementType.erasedType(), 0); return new ResolvedType(emptyArray.getClass(), typeBindings, elementType); } if (mainType instanceof TypeVariable) { return _fromVariable(context, (TypeVariable) mainType, typeBindings); } if (mainType instanceof WildcardType) { return _fromAny(context, ((WildcardType) mainType).getUpperBounds()[0], typeBindings); } // should never get here... throw new IllegalArgumentException("Unrecognized type class: "+mainType.getClass().getName()); } private ResolvedType _fromClass(ClassStack context, Class rawType, TypeBindings typeBindings) { final ClassKey key = new ClassKey(rawType, 0); if (rawType.isPrimitive()) { ResolvedType type = _primitives.get(key); if (type != null) { return type; } } if (context == null) { context = new ClassStack(rawType); } else { ClassStack prev = context.find(rawType); if (prev != null) { // Self-reference: needs special handling, then... RecursiveType selfRef = new RecursiveType(rawType, typeBindings); prev.addSelfReference(selfRef); return selfRef; } // no, can just add context = context.child(rawType); } ResolvedType type; if (typeBindings.isEmpty()) { synchronized (_cache) { type = _cache.get(key); if (type != null) { return type; } } type = _constructType(context, rawType, typeBindings); synchronized (_cache) { if (_cache.size() >= 100) { // so hash table max 128 entries _cache.clear(); } _cache.put(key, type); } } else { type = _constructType(context, rawType, typeBindings); } context.resolveSelfReferences(type); return type; } private ResolvedType _constructType(ClassStack context, Class rawType, TypeBindings typeBindings) { // Ok: no easy shortcut, let's figure out type of type... if (rawType.isArray()) { ResolvedType elementType = _fromAny(context, rawType.getComponentType(), typeBindings); return new ResolvedType(rawType, typeBindings, elementType); } // For other types super interfaces are needed... if (rawType.isInterface()) { return new ResolvedType(rawType, typeBindings, _resolveSuperInterfaces(context, rawType, typeBindings)); } return new ResolvedType(rawType, _resolveSuperClass(context, rawType, typeBindings), typeBindings, _resolveSuperInterfaces(context, rawType, typeBindings)); } private ResolvedType[] _resolveSuperInterfaces(ClassStack context, Class rawType, TypeBindings typeBindings) { Type[] types = rawType.getGenericInterfaces(); if (types == null || types.length == 0) { return NO_TYPES; } int len = types.length; ResolvedType[] resolved = new ResolvedType[len]; for (int i = 0; i < len; ++i) { resolved[i] = _fromAny(context, types[i], typeBindings); } return resolved; } private ResolvedType _resolveSuperClass(ClassStack context, Class rawType, TypeBindings typeBindings) { Type parent = rawType.getGenericSuperclass(); if (parent == null) { return null; } return _fromAny(context, parent, typeBindings); } private ResolvedType _fromParamType(ClassStack context, ParameterizedType ptype, TypeBindings parentBindings) { Class rawType = (Class) ptype.getRawType(); Type[] params = ptype.getActualTypeArguments(); int len = params.length; ResolvedType[] types = new ResolvedType[len]; for (int i = 0; i < len; ++i) { types[i] = _fromAny(context, params[i], parentBindings); } TypeBindings newBindings = TypeBindings.create(rawType, types); return _fromClass(context, rawType, newBindings); } private ResolvedType _fromVariable(ClassStack context, TypeVariable variable, TypeBindings typeBindings) { String name = variable.getName(); ResolvedType type = typeBindings.findBoundType(name); if (type != null) { return type; } if (typeBindings.hasUnbound(name)) { return TYPE_OBJECT; } typeBindings = typeBindings.withUnboundVariable(name); Type[] bounds = variable.getBounds(); return _fromAny(context, bounds[0], typeBindings); } } jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/resources/000077500000000000000000000000001323200335100246745ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/resources/META-INF/000077500000000000000000000000001323200335100260345ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/resources/META-INF/LICENSE000066400000000000000000000005141323200335100270410ustar00rootroot00000000000000This copy of Jackson JSON processor streaming parser/generator is licensed under the Apache (Software) License, version 2.0 ("the License"). See the License for details about distribution rights, and the specific rights regarding derivate works. You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0 jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/main/resources/META-INF/NOTICE000066400000000000000000000014661323200335100267470ustar00rootroot00000000000000# Jackson JSON processor Jackson is a high-performance, Free/Open Source JSON processing library. It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has been in development since 2007. It is currently developed by a community of developers, as well as supported commercially by FasterXML.com. ## Licensing Jackson core and extension components may licensed under different licenses. To find the details that apply to this artifact see the accompanying LICENSE file. For more information, including possible other licensing options, contact FasterXML.com (http://fasterxml.com). ## Credits A list of contributors may be found from CREDITS file, which is included in some artifacts (usually source distributions); but is always available from the source code management (SCM) system project uses. jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/000077500000000000000000000000001323200335100227155ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/000077500000000000000000000000001323200335100236365ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/000077500000000000000000000000001323200335100244145ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/000077500000000000000000000000001323200335100264215ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/000077500000000000000000000000001323200335100300515ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/000077500000000000000000000000001323200335100304645ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/failing/000077500000000000000000000000001323200335100320755ustar00rootroot00000000000000ReadEnumMap21Test.java000066400000000000000000000027521323200335100360300ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/failingpackage com.fasterxml.jackson.jr.failing; import java.util.*; import com.fasterxml.jackson.jr.ob.JSON; import com.fasterxml.jackson.jr.ob.TestBase; // for [jackson-jr#21] public class ReadEnumMap21Test extends TestBase { enum DEF { D, E, F; } static class WithEnumMap { private Map values; WithEnumMap() { } public WithEnumMap(DEF key, String value) { values = new LinkedHashMap(); values.put(key, value); } public Map getValues() { return values; } public void setValues(Map v) { values = v; } } // [issue#21] public void testMapWithEnumKey() throws Exception { WithEnumMap input = new WithEnumMap(DEF.E, "bar"); // verify serialization, should be ok: String json = JSON.std.asString(input); assertEquals(aposToQuotes("{'values':{'E':'bar'}}"), json); // and then get it back too WithEnumMap result = JSON.std.beanFrom(WithEnumMap.class, json); assertNotNull(result); Map map = result.getValues(); assertNotNull(map); assertEquals(1, map.size()); Map.Entry entry = map.entrySet().iterator().next(); assertEquals("bar", entry.getValue()); if (!(entry.getKey() instanceof DEF)) { fail("Expected key to be of type ABC, is: "+entry.getKey().getClass().getName()); } assertEquals(DEF.E, entry.getKey()); } } ReadWithCtors25Test.java000066400000000000000000000017621323200335100364200ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/failingpackage com.fasterxml.jackson.jr.failing; import com.fasterxml.jackson.jr.ob.JSON; import com.fasterxml.jackson.jr.ob.TestBase; // for [jackson-jr#25], allowing single-int constructors public class ReadWithCtors25Test extends TestBase { static class FromInt1 { protected int value; public FromInt1(int v) { value = v; } } static class FromInt2 { protected int value; public FromInt2(Integer v) { value = v.intValue(); } } /* /********************************************************************** /* Test methdods /********************************************************************** */ public void testIntCtor() throws Exception { FromInt1 output = JSON.std.beanFrom(FromInt1.class, "123"); assertNotNull(output); assertEquals(123L, output.value); FromInt2 output2 = JSON.std.beanFrom(FromInt2.class, "456"); assertNotNull(output2); assertEquals(456L, output2.value); } } jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/000077500000000000000000000000001323200335100310645ustar00rootroot00000000000000IndentationTest.java000066400000000000000000000012471323200335100347700ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/obpackage com.fasterxml.jackson.jr.ob; import java.util.*; import com.fasterxml.jackson.jr.ob.JSON; public class IndentationTest extends TestBase { public void testSimpleList() throws Exception { Map map = new LinkedHashMap(); map.put("a", 1); map.put("b", 2); // By default, no indentation assertEquals("{\"a\":1,\"b\":2}", JSON.std.asString(map)); // but with simple change... assertEquals("{\n" +" \"a\" : 1,\n" +" \"b\" : 2\n" +"}", JSON.std.with(JSON.Feature.PRETTY_PRINT_OUTPUT).asString(map)); } } MediaItem.java000066400000000000000000000070621323200335100335130ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/obpackage com.fasterxml.jackson.jr.ob; import java.util.*; public class MediaItem { public enum Player { JAVA, FLASH; } public enum Size { SMALL, LARGE; } private List _photos; private Content _content; public MediaItem() { } public MediaItem(Content c) { _content = c; } public void addPhoto(Photo p) { if (_photos == null) { _photos = new ArrayList(); } _photos.add(p); } public List getImages() { return _photos; } public void setImages(List p) { _photos = p; } public Content getContent() { return _content; } public void setContent(Content c) { _content = c; } /* /********************************************************** /* Helper types /********************************************************** */ public static class Photo { private String _uri; private String _title; private int _width; private int _height; private Size _size; public Photo() {} public Photo(String uri, String title, int w, int h, Size s) { _uri = uri; _title = title; _width = w; _height = h; _size = s; } public String getUri() { return _uri; } public String getTitle() { return _title; } public int getWidth() { return _width; } public int getHeight() { return _height; } public Size getSize() { return _size; } public void setUri(String u) { _uri = u; } public void setTitle(String t) { _title = t; } public void setWidth(int w) { _width = w; } public void setHeight(int h) { _height = h; } public void setSize(Size s) { _size = s; } } public static class Content { private Player _player; private String _uri; private String _title; private int _width; private int _height; private String _format; private long _duration; private long _size; private int _bitrate; private List _persons; private String _copyright; public Content() { } public void addPerson(String p) { if (_persons == null) { _persons = new ArrayList(); } _persons.add(p); } public Player getPlayer() { return _player; } public String getUri() { return _uri; } public String getTitle() { return _title; } public int getWidth() { return _width; } public int getHeight() { return _height; } public String getFormat() { return _format; } public long getDuration() { return _duration; } public long getSize() { return _size; } public int getBitrate() { return _bitrate; } public List getPersons() { return _persons; } public String getCopyright() { return _copyright; } public void setPlayer(Player p) { _player = p; } public void setUri(String u) { _uri = u; } public void setTitle(String t) { _title = t; } public void setWidth(int w) { _width = w; } public void setHeight(int h) { _height = h; } public void setFormat(String f) { _format = f; } public void setDuration(long d) { _duration = d; } public void setSize(long s) { _size = s; } public void setBitrate(int b) { _bitrate = b; } public void setPersons(List p) { _persons = p; } public void setCopyright(String c) { _copyright = c; } } } NullHandlingTest.java000066400000000000000000000013221323200335100350650ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/obpackage com.fasterxml.jackson.jr.ob; import java.util.LinkedHashMap; import java.util.Map; import com.fasterxml.jackson.jr.ob.JSON; public class NullHandlingTest extends TestBase { // Test to verify that outputting of nulls is configurable public void testMapNullEntries() throws Exception { Map map = new LinkedHashMap(); map.put("a", 1); map.put("b", null); // By default we do NOT write null-valued entries: assertEquals("{\"a\":1}", JSON.std.asString(map)); // but we can disable it easily assertEquals("{\"a\":1,\"b\":null}", JSON.std.with(JSON.Feature.WRITE_NULL_PROPERTIES).asString(map)); } } ReadBeansTest.java000066400000000000000000000164201323200335100343370ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/obpackage com.fasterxml.jackson.jr.ob; import java.util.*; import com.fasterxml.jackson.jr.ob.JSON; public class ReadBeansTest extends TestBase { static class TestBean { protected int x; protected NameBean name; public void setName(NameBean n) { name = n; } public void setX(int x) { this.x = x; } public int getX() { return x; } public NameBean getName() { return name; } } static class NameBean { protected String first, last; public String getFirst() { return first; } public String getLast() { return last; } public void setFirst(String n) { first = n; } public void setLast(String n) { last = n; } } static class MapBean { protected Map stuff; public Map getStuff() { return stuff; } public void setStuff(Map s) { stuff = s; } } static class NameListBean { protected List names; public List getNames() { return names; } public void setNames(List n) { names = n; } } interface Bean { public void setValue(T t); } static class LongBean implements Bean { Long value; @Override public void setValue(Long v) { value = v; } } /* /********************************************************************** /* Test methdods /********************************************************************** */ public void testSimpleBean() throws Exception { final String INPUT = aposToQuotes("{'name':{'first':'Bob','last':'Burger'},'x':13}"); TestBean bean = JSON.std.beanFrom(TestBean.class, INPUT); assertNotNull(bean); assertEquals(13, bean.x); assertNotNull(bean.name); assertEquals("Bob", bean.name.first); assertEquals("Burger", bean.name.last); } public void testUnknownProps() throws Exception { final String INPUT = aposToQuotes("{'first':'Bob','middle':'Eugene', 'last':'Smith'}"); // First: fine if marked as such NameBean name = JSON.std .without(JSON.Feature.FAIL_ON_UNKNOWN_BEAN_PROPERTY) .beanFrom(NameBean.class, INPUT); assertNotNull(name); assertEquals("Bob", name.first); assertEquals("Smith", name.last); // but not if check enabled try { name = JSON.std .with(JSON.Feature.FAIL_ON_UNKNOWN_BEAN_PROPERTY) .beanFrom(NameBean.class, INPUT); fail("Should have thrown exception"); } catch (JSONObjectException e) { verifyException(e, "unrecognized JSON property 'middle'"); } } public void testPOJOWithList() throws Exception { final String INPUT = aposToQuotes("{'names': [ { 'first':'John','last':'Smith' }," +"{'first':'Bob','last':'Burger' } ] }"); NameListBean list = JSON.std.beanFrom(NameListBean.class, INPUT); assertNotNull(list); assertNotNull(list.names); assertEquals(2, list.names.size()); NameBean name = list.names.get(1); assertEquals("Burger", name.getLast()); } public void testPOJOWithMap() throws Exception { final String INPUT = aposToQuotes("{'stuff': { 'a':3, 'b':4 } }"); MapBean map = JSON.std.beanFrom(MapBean.class, INPUT); assertNotNull(map); assertNotNull(map.stuff); assertEquals(2, map.stuff.size()); assertEquals(Integer.valueOf(4), map.stuff.get("b")); } public void testSimpleBeanCollections() throws Exception { final String INPUT = aposToQuotes("[" +"{'name':{'first':'Bob','last':'Burger'},'x':13}" +",{'x':-145,'name':{'first':'Billy','last':'Bacon'}}" +"]"); // First, bean array TestBean[] beans = JSON.std.arrayOfFrom(TestBean.class, INPUT); assertNotNull(beans); assertEquals(2, beans.length); assertEquals(13, beans[0].x); assertEquals("Bob", beans[0].name.first); assertEquals("Burger", beans[0].name.last); assertEquals(-145, beans[1].x); assertEquals("Billy", beans[1].name.first); assertEquals("Bacon", beans[1].name.last); // then List List beans2 = JSON.std.listOfFrom(TestBean.class, INPUT); assertNotNull(beans2); assertEquals(2, beans2.size()); assertEquals(13, beans2.get(0).x); assertEquals("Bob", beans2.get(0).name.first); assertEquals("Burger", beans2.get(0).name.last); assertEquals(-145, beans2.get(1).x); assertEquals("Billy", beans2.get(1).name.first); assertEquals("Bacon", beans2.get(1).name.last); } public void testJvmSerializersPOJO() throws Exception { MediaItem.Content content = new MediaItem.Content(); content.setPlayer(MediaItem.Player.JAVA); content.setUri("http://javaone.com/keynote.mpg"); content.setTitle("Javaone Keynote"); content.setWidth(640); content.setHeight(480); content.setFormat("video/mpeg4"); content.setDuration(18000000L); content.setSize(58982400L); content.setBitrate(262144); content.setCopyright("None"); content.addPerson("Bill Gates"); content.addPerson("Steve Jobs"); MediaItem input = new MediaItem(content); final String IMAGE_URI1 = "http://javaone.com/keynote_large.jpg"; input.addPhoto(new MediaItem.Photo(IMAGE_URI1, "Javaone Keynote", 1024, 768, MediaItem.Size.LARGE)); input.addPhoto(new MediaItem.Photo("http://javaone.com/keynote_small.jpg", "Javaone Keynote", 320, 240, MediaItem.Size.SMALL)); String json = JSON.std.asString(input); MediaItem result = JSON.std .with(JSON.Feature.FAIL_ON_UNKNOWN_BEAN_PROPERTY) .beanFrom(MediaItem.class, json); assertNotNull(result); assertEquals(262144, result.getContent().getBitrate()); assertEquals("Steve Jobs", result.getContent().getPersons().get(1)); List im = result.getImages(); assertEquals(2, im.size()); assertEquals(MediaItem.Photo.class, im.get(0).getClass()); MediaItem.Photo im1 = (MediaItem.Photo) im.get(0); assertNotNull(im1); assertEquals(IMAGE_URI1, im1.getUri()); } // For [#15] public void testLongBind() throws Exception { final String INPUT = "{\"value\":2}"; LongBean bean = JSON.std.beanFrom(LongBean.class, INPUT); assertNotNull(bean); assertEquals(Long.valueOf(2L), bean.value); } public void testPojoArray() throws Exception { LongBean[] empty = JSON.std .with(JSON.Feature.READ_JSON_ARRAYS_AS_JAVA_ARRAYS) .arrayOfFrom(LongBean.class, "[ ]"); assertNotNull(empty); assertEquals(0, empty.length); LongBean[] result = JSON.std .with(JSON.Feature.READ_JSON_ARRAYS_AS_JAVA_ARRAYS) .arrayOfFrom(LongBean.class, "[{\"value\":3}]"); assertNotNull(result); assertEquals(1, result.length); assertEquals(3L, result[0].value.longValue()); } } ReadFeaturesTest.java000066400000000000000000000026771323200335100350760ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/obpackage com.fasterxml.jackson.jr.ob; import com.fasterxml.jackson.jr.ob.JSON; public class ReadFeaturesTest extends TestBase { static class IsBean { public boolean isEnabled() { return true; } public int getValue() { return 42; } } /* /********************************************************************** /* Test methdods /********************************************************************** */ public void testPojoWithIsGetter() throws Exception { assertTrue(JSON.std.isEnabled(JSON.Feature.USE_IS_GETTERS)); String json; json = JSON.std.asString(new IsBean()); // by default, will use 'is-getter': assertEquals(aposToQuotes("{'enabled':true,'value':42}"), json); // but can disable json = JSON.std .without(JSON.Feature.USE_IS_GETTERS) .asString(new IsBean()); assertEquals(aposToQuotes("{'value':42}"), json); } public void testFailOnDupMapKeys() throws Exception { JSON j = JSON.std.with(JSON.Feature.FAIL_ON_DUPLICATE_MAP_KEYS); assertTrue(j.isEnabled(JSON.Feature.FAIL_ON_DUPLICATE_MAP_KEYS)); final String json = "{\"a\":1,\"b\":2,\"b\":3,\"c\":4}"; try { /*Map map =*/ j.mapFrom(json); fail("Should not pass"); } catch (JSONObjectException e) { verifyException(e, "Duplicate key"); } } } ReadMapTest.java000066400000000000000000000014421323200335100340220ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/obpackage com.fasterxml.jackson.jr.ob; import java.util.*; import com.fasterxml.jackson.jr.ob.JSON; // for [jackson-jr#49], where `DeferredMap` explodes public class ReadMapTest extends TestBase { public void testIssues49() throws Exception { for (int i : new int[] { 7, 99, 513, 1099, 3003, 5005, 10001, 90003, 111111 }) { testLargeJson(i); } } private void testLargeJson(int size) throws Exception { Map map = new HashMap(); for (int i = 0; i < size; i++) { map.put("" + i, new HashMap()); } String json = JSON.std.asString(map); Map result = JSON.std.mapFrom(json); assertNotNull(result); assertEquals(size, result.size()); } } ReadSimpleTest.java000066400000000000000000000104561323200335100345430ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/obpackage com.fasterxml.jackson.jr.ob; import java.util.*; import com.fasterxml.jackson.jr.ob.JSON; import com.fasterxml.jackson.jr.ob.JSON.Feature; public class ReadSimpleTest extends TestBase { enum ABC { A, B, C; } /* /********************************************************************** /* Tests for Lists/Collections /********************************************************************** */ public void testSimpleList() throws Exception { final String INPUT = "[1,2,3]"; Object ob = JSON.std.anyFrom(INPUT); // default mapping should be to List: assertTrue(ob instanceof List); assertEquals(3, ((List) ob).size()); // actually, verify with write... assertEquals(INPUT, JSON.std.asString(ob)); // but same should be possible with explicit call as well List list = JSON.std.listFrom(INPUT); assertEquals(3, list.size()); assertEquals(INPUT, JSON.std.asString(list)); } /* /********************************************************************** /* Tests for arrays /********************************************************************** */ public void testSimpleArray() throws Exception { _testArray("[true,\"abc\",3]", 3); } public void testEmptyArray() throws Exception { _testArray("[]", 0); } // separate tests since code path differs public void testSingleElementArray() throws Exception { _testArray("[12]", 1); } private void _testArray(String input, int expCount) throws Exception { Object ob; // first: can explicitly request an array: ob = JSON.std.arrayFrom(input); assertTrue(ob instanceof Object[]); assertEquals(expCount, ((Object[]) ob).length); assertEquals(input, JSON.std.asString(ob)); // or, with ob = JSON.std .arrayOfFrom(Object.class, input); assertTrue(ob instanceof Object[]); assertEquals(expCount, ((Object[]) ob).length); assertEquals(input, JSON.std.asString(ob)); ob = JSON.std .with(JSON.Feature.READ_JSON_ARRAYS_AS_JAVA_ARRAYS) .arrayOfFrom(Object.class, input); assertTrue(ob instanceof Object[]); assertEquals(expCount, ((Object[]) ob).length); assertEquals(input, JSON.std.asString(ob)); // or by changing default mapping: ob = JSON.std.with(Feature.READ_JSON_ARRAYS_AS_JAVA_ARRAYS).anyFrom(input); assertTrue(ob instanceof Object[]); assertEquals(expCount, ((Object[]) ob).length); assertEquals(input, JSON.std.asString(ob)); } /* /********************************************************************** /* Tests for Maps /********************************************************************** */ public void testSimpleMap() throws Exception { final String INPUT = "{\"a\":1,\"b\":true,\"c\":3}"; Object ob = JSON.std.anyFrom(INPUT); assertTrue(ob instanceof Map); assertEquals(3, ((Map) ob).size()); // actually, verify with write... assertEquals(INPUT, JSON.std.asString(ob)); // or, via explicit Map read Map stuff = JSON.std.mapFrom(INPUT); assertEquals(3, stuff.size()); } /* /********************************************************************** /* Other tests /********************************************************************** */ public void testSimpleMixed() throws Exception { final String INPUT = "{\"a\":[1,2,{\"b\":true},3],\"c\":3}"; Object ob = JSON.std.anyFrom(INPUT); assertTrue(ob instanceof Map); assertEquals(2, ((Map) ob).size()); Object list = (((Map) ob).get("a")); assertTrue(list instanceof List); // actually, verify with write... assertEquals(INPUT, JSON.std.asString(ob)); } public void testSimpleEnums() throws Exception { // First using index ABC abc = JSON.std.beanFrom(ABC.class, String.valueOf(ABC.B.ordinal())); assertEquals(ABC.B, abc); // then from name abc = JSON.std.beanFrom(ABC.class, quote("C")); assertEquals(ABC.C, abc); } } ReadWithCtorsTest.java000066400000000000000000000023371323200335100352370ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/obpackage com.fasterxml.jackson.jr.ob; import com.fasterxml.jackson.jr.ob.JSON; public class ReadWithCtorsTest extends TestBase { static class FromString { protected String value; public FromString(String v) { value = v; } } static class FromLong1 { protected long value; public FromLong1(long v) { value = v; } } static class FromLong2 { protected long value; public FromLong2(Long v) { value = v.longValue(); } } /* /********************************************************************** /* Test methdods /********************************************************************** */ public void testStringCtor() throws Exception { FromString output = JSON.std.beanFrom(FromString.class, quote("abc")); assertNotNull(output); assertEquals("abc", output.value); } public void testLongCtor() throws Exception { FromLong1 output = JSON.std.beanFrom(FromLong1.class, "123"); assertNotNull(output); assertEquals(123L, output.value); FromLong2 output2 = JSON.std.beanFrom(FromLong2.class, "456"); assertNotNull(output2); assertEquals(456L, output2.value); } } RoundtripTest.java000066400000000000000000000034021323200335100344750ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/obpackage com.fasterxml.jackson.jr.ob; import java.io.*; public class RoundtripTest extends TestBase { public void testSimple() throws Exception { MediaItem input = buildItem(); String json = JSON.std.asString(input); // Let's exercise multiple styles of input sources assertEquals(json, _readWrite(json)); byte[] b = json.getBytes("UTF-8"); assertEquals(json, _readWrite(b)); assertEquals(json, _readWrite(new ByteArrayInputStream(b))); assertEquals(json, _readWrite(new StringReader(json))); assertEquals(json, _readWrite(json.toCharArray())); } private String _readWrite(Object json) throws Exception { MediaItem item = JSON.std.beanFrom(MediaItem.class, json); return JSON.std.asString(item); } private MediaItem buildItem() { MediaItem.Content content = new MediaItem.Content(); content.setUri("http://javaone.com/keynote.mpg"); content.setTitle("Javaone Keynote"); content.setWidth(640); content.setHeight(480); content.setFormat("video/mpg4"); content.setDuration(18000000); content.setSize(58982400L); content.setBitrate(262144); content.setPlayer(MediaItem.Player.JAVA); content.setCopyright("None"); content.addPerson("Bill Gates"); content.addPerson("Steve Jobs"); MediaItem item = new MediaItem(content); item.addPhoto(new MediaItem.Photo("http://javaone.com/keynote_large.jpg", "Javaone Keynote", 1024, 768, MediaItem.Size.LARGE)); item.addPhoto(new MediaItem.Photo("http://javaone.com/keynote_small.jpg", "Javaone Keynote", 320, 240, MediaItem.Size.SMALL)); return item; } } SimpleComposerTest.java000066400000000000000000000105631323200335100354560ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/obpackage com.fasterxml.jackson.jr.ob; import java.util.*; import com.fasterxml.jackson.jr.ob.JSON; public class SimpleComposerTest extends TestBase { public static class NameBean { String first; public NameBean(String f) { first = f; } public String getFirst() { return first; } public void setFirst(String s) { first = s; } } public void testSimpleNonNestedObject() throws Exception { String json = JSON.std.composeString() .startObject() .put("a", 1) .put("b", false) .end() .finish(); assertEquals("{\"a\":1,\"b\":false}", json); } public void testSimpleNonNestedArray() throws Exception { String json = JSON.std.composeString() .startArray() .add(true) .add("abc") .add(75) .end() .finish(); assertEquals("[true,\"abc\",75]", json); } public void testNestedObject() throws Exception { String json = JSON.std.composeString() .startObject() .put("a", 1) .startObjectField("ob") .startObjectField("x") .startObjectField("inner") .end() .end() .end() .end() .finish(); assertEquals("{\"a\":1,\"ob\":{\"x\":{\"inner\":{}}}}", json); } public void testNestedArray() throws Exception { String json = JSON.std.composeString() .startArray() .startArray() .add(true) .startArray() .startArray().end() .add(13) .end() .end() .end() .finish(); assertEquals("[[true,[[],13]]]", json); } public void testNestedMixed() throws Exception { byte[] json = JSON.std.composeBytes() .startObject() .put("a", 1) .startArrayField("arr") .add(1).add(2).add(3) .end() .startObjectField("ob") .put("x", 3) .put("y", 4) .startArrayField("args").add("none").end() .end() .put("last", true) .end() .finish(); assertEquals("{\"a\":1,\"arr\":[1,2,3],\"ob\":{\"x\":3,\"y\":4," +"\"args\":[\"none\"]},\"last\":true}", new String(json, "UTF-8")); } public void testListComposer() throws Exception { List list = JSON.std .composeCollection(new ArrayList()) .add(true) .add("foo") .add(13) .startArray() .add(55) .end() .finish(); assertEquals("[true,\"foo\",13,[55]]", JSON.std.asString(list)); list = JSON.std.composeList() .add(-3) .startObject() .put("a", 1) .put("b", 2) .end() .finish(); assertEquals("[-3,{\"a\":1,\"b\":2}]", JSON.std.asString(list)); } public void testComposerWithPojo() throws Exception { String json = JSON.std.composeString() .startArray() .addObject(new NameBean("Bob")) .startObject() .putObject("name", new NameBean("Bill")) .end() .end() .finish(); assertEquals(aposToQuotes("[{'first':'Bob'},{'name':{'first':'Bill'}}]"), json); } public void testComposerWithIndent() throws Exception { String json = JSON.std .with(JSON.Feature.PRETTY_PRINT_OUTPUT) .composeString() .startObject() .put("name", "Bill") .end() .finish(); assertEquals(aposToQuotes("{\n" +" 'name' : 'Bill'\n" +"}"), json); } } SimpleFieldTest.java000066400000000000000000000020041323200335100347010ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/obpackage com.fasterxml.jackson.jr.ob; import com.fasterxml.jackson.jr.ob.JSON; public class SimpleFieldTest extends TestBase { static class XY { public int x; private int y; public XY(int x0, int y0) { x = x0; y = y0; } protected XY() { } public int getY() { return y; } public void setY(int value) { y = value; } } public void testDefaulSettings() { assertFalse(JSON.std.isEnabled(JSON.Feature.USE_FIELDS)); } public void testSerializeWithField() throws Exception { String json = JSON.std.with(JSON.Feature.USE_FIELDS) .asString(new XY(1, 2)); assertEquals(aposToQuotes("{'x':1,'y':2}"), json); } public void testDeserializeWithField() throws Exception { XY result = JSON.std.with(JSON.Feature.USE_FIELDS) .beanFrom(XY.class, aposToQuotes("{'x':3,'y':4}")); assertEquals(4, result.getY()); assertEquals(3, result.x); } } TestBase.java000066400000000000000000000014541323200335100333660ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/obpackage com.fasterxml.jackson.jr.ob; import java.util.Arrays; import junit.framework.TestCase; public abstract class TestBase extends TestCase { protected void verifyException(Throwable e, String... matches) { String msg = e.getMessage(); String lmsg = (msg == null) ? "" : msg.toLowerCase(); for (String match : matches) { String lmatch = match.toLowerCase(); if (lmsg.indexOf(lmatch) >= 0) { return; } } fail("Expected an exception with one of substrings ("+Arrays.asList(matches)+"): got one with message \""+msg+"\""); } protected String quote(String str) { return "\"" + str + "\""; } protected String aposToQuotes(String json) { return json.replace("'", "\""); } } WriteBeansTest.java000066400000000000000000000057031323200335100345600ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/obpackage com.fasterxml.jackson.jr.ob; import java.util.*; import com.fasterxml.jackson.jr.ob.JSON.Feature; public class WriteBeansTest extends TestBase { static class TestBean { public int getX() { return 1; } public void setX(int x) { } public int getY() { return 3; } } static class BinaryBean { protected final static byte[] STUFF = new byte[] { 1, 2, 3, 4, 5, 6, 7 }; public byte[] getStuff() { return STUFF; } } static class BeanBase { public int _value; public int getValue() { return _value; } public void setValue(int v) { _value = v; } } static class BaseImpl extends BeanBase { public int _extra; protected BaseImpl() { } public BaseImpl(int v, int x) { _value = v; _extra = x; } public int getExtra() { return _extra; } public void setExtra(int v) { _extra = v; } } public void testBinary() throws Exception { String json = JSON.std.asString(new BinaryBean()); Map map = JSON.std.mapFrom(json); if (1 != map.size()) { fail("Wrong Map contents: "+json); } String base64 = (String) map.get("stuff"); assertNotNull(base64); assertEquals("AQIDBAUGBw==", base64); } public void testSimpleMap() throws Exception { // first: with default settings, should serialize 2 props String json = JSON.std.asString(new TestBean()); Map map = JSON.std.mapFrom(json); if ((2 != map.size()) || !Integer.valueOf(1).equals(map.get("x")) || !Integer.valueOf(3).equals(map.get("y")) ){ fail("Wrong Map contents (expected 'x' and 'y' for JSON: "+json); } // and then different configs json = JSON.std.without(Feature.WRITE_READONLY_BEAN_PROPERTIES) .asString(new TestBean()); map = JSON.std.mapFrom(json); if ((1 != map.size()) || !Integer.valueOf(1).equals(map.get("x")) ){ fail("Wrong Map contents (expected just 'x' for JSON: "+json); } } // Make sure we handle stuff from base class too public void testMethodsFromSuperclass() throws Exception { String json = JSON.std.asString(new BaseImpl(1, 2)); Map map = JSON.std.mapFrom(json); if ((2 != map.size()) || !Integer.valueOf(1).equals(map.get("value")) || !Integer.valueOf(2).equals(map.get("extra")) ){ fail("Wrong Map contents (expected 'value' and 'extra' for JSON: "+json); } BaseImpl result = JSON.std.beanFrom(BaseImpl.class, aposToQuotes("{ 'extra':5, 'value':-245 }")); assertEquals(5, result.getExtra()); assertEquals(-245, result.getValue()); } } WriteDatesTest.java000066400000000000000000000016031323200335100345630ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/obpackage com.fasterxml.jackson.jr.ob; import java.util.Date; import com.fasterxml.jackson.jr.ob.JSON.Feature; public class WriteDatesTest extends TestBase { // For [jackson-jr#29] public void testSimpleDates() throws Exception { final Date input = new Date(0L); JSON j = JSON.std; assertFalse(j.isEnabled(Feature.WRITE_DATES_AS_TIMESTAMP)); String json = j.asString(input); // What to test? For now, accept two variants we may get, depending // on timezone (which we can not, alas, control) if (!json.contains("Dec 31") && !json.contains("Jan 01")) { fail("Invalid output: "+json); } j = j.with(Feature.WRITE_DATES_AS_TIMESTAMP); assertTrue(j.isEnabled(Feature.WRITE_DATES_AS_TIMESTAMP)); json = j.asString(input); assertEquals("0", json); } } WriteSimpleTest.java000066400000000000000000000113341323200335100347560ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/obpackage com.fasterxml.jackson.jr.ob; import java.io.File; import java.net.URI; import java.net.URL; import java.util.*; import com.fasterxml.jackson.jr.ob.JSON; import com.fasterxml.jackson.jr.ob.JSON.Feature; public class WriteSimpleTest extends TestBase { final static class POJO { public int value = 3; public POJO() { } public POJO(int v) { value = v; } } enum ABC { A, B, C; } final static class Address { public String name; public Address(String n) { name = n; } } /* /********************************************************************** /* Test methdods /********************************************************************** */ public void testSimpleList() throws Exception { List stuff = new LinkedList(); stuff.add("x"); stuff.add(true); stuff.add(123); assertEquals("[\"x\",true,123]", JSON.std.asString(stuff)); } public void testSimpleMap() throws Exception { Map stuff = new LinkedHashMap(); stuff.put("a", 15); stuff.put("b", Boolean.TRUE); stuff.put("c", "foobar"); stuff.put("d", UUID.fromString("8f88e079-7dc6-46f8-abfb-a533130f4ea0")); stuff.put("e", new URL("https://github.com/FasterXML/jackson-jr?a=x&b=y")); stuff.put("f", URI.create("https://github.com/FasterXML/jackson-jr?c=x&c=y")); assertEquals("{\"a\":15,\"b\":true,\"c\":\"foobar\",\"d\":\"8f88e079-7dc6-46f8-abfb-a533130f4ea0\"," + "\"e\":\"https://github.com/FasterXML/jackson-jr?a=x&b=y\",\"f\":\"https://github.com/FasterXML/jackson-jr?c=x&c=y\"}", JSON.std.asString(stuff)); } public void testSimpleIntContainers() throws Exception { assertEquals("[1,2,3]", JSON.std.asString(new int[] { 1, 2, 3 })); assertEquals("[1,2,3]", JSON.std.asString(new Integer[] { 1, 2, 3 })); List list = new ArrayList(); list.add(4); list.add(-8); assertEquals("[4,-8]", JSON.std.asString(list)); } public void testSimpleBooleanArray() throws Exception { assertEquals("[true,false]", JSON.std.asString(new boolean[] { true, false })); assertEquals("[true,false]", JSON.std.asString(new Boolean[] { true, false })); } public void testSimpleStringArray() throws Exception { assertEquals(aposToQuotes("['abc','def']"), JSON.std.asString(new String[] { "abc", "def" })); } public void testNest() throws Exception { Map stuff = new LinkedHashMap(); List list = new ArrayList(); list.add(123); list.add(456); stuff.put("first", list); Map second = new LinkedHashMap(); stuff.put("second", second); second.put("foo", "bar"); second.put("bar", new ArrayList()); assertEquals("{\"first\":[123,456],\"second\":{\"foo\":\"bar\",\"bar\":[]}}", JSON.std.asString(stuff)); } public void testKnownSimpleTypes() throws Exception { final String URL_STR = "http://fasterxml.com"; assertEquals(quote(URL_STR), JSON.std.asString(new URI(URL_STR))); final String PATH = "/foo/bar.txt"; assertEquals(quote(PATH), JSON.std.asString(new File(PATH))); assertEquals(quote("B"), JSON.std.asString(ABC.B)); assertEquals("1", JSON.std.with(Feature.WRITE_ENUMS_USING_INDEX).asString(ABC.B)); } public void testUnknownType() throws Exception { try { String json = JSON.std.with(JSON.Feature.FAIL_ON_UNKNOWN_TYPE_WRITE) .without(JSON.Feature.HANDLE_JAVA_BEANS) .asString(new POJO()); fail("Should have failed: instead got: "+json); } catch (Exception e) { verifyException(e, "unrecognized type"); verifyException(e, "POJO"); } } // For [jackson-jr#16] public void testTypedMaps() throws Exception { final Address from = new Address("xyz"); final Map> to = new HashMap>(); to.put("static_addr", new HashSet
()); to.get("static_addr").add(new Address("abc")); final Map temp = new HashMap(); temp.put("from", from); temp.put("TO", to); String json = JSON.std.asString(temp); assertNotNull(json); // and sanity check for back direction Map map = JSON.std.mapFrom(json); assertNotNull(map); assertEquals(2, map.size()); } } jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/impl/000077500000000000000000000000001323200335100320255ustar00rootroot00000000000000TypeDetectorTest.java000066400000000000000000000051601323200335100360660ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-objects/src/test/java/com/fasterxml/jackson/jr/ob/implpackage com.fasterxml.jackson.jr.ob.impl; import java.util.*; import com.fasterxml.jackson.jr.ob.JSON; import com.fasterxml.jackson.jr.ob.TestBase; import com.fasterxml.jackson.jr.ob.impl.TypeDetector; public class TypeDetectorTest extends TestBase { static class TestBean { public int getX() { return 1; } public void setX(int x) { } public String getName() { return null; } public void setY(int y) { } public int bebop() { return 3; } public void zipdoo(int value) { } // not a regular getter (could be indexed) public void setEmUp(int index, String value) { } } interface Bean { public void setValue(T t); } static class LongBean implements Bean { Long value; @Override public void setValue(Long v) { value = v; } } /* /********************************************************************** /* Test methdods /********************************************************************** */ public void testBasicTypeDetectionForSer() { TypeDetector td = TypeDetector.blueprint(JSON.Feature.defaults()); assertEquals(TypeDetector.SER_STRING, td.findSerializationType(String.class)); assertEquals(TypeDetector.SER_CHAR_ARRAY, td.findSerializationType(char[].class)); assertEquals(TypeDetector.SER_INT_ARRAY, td.findSerializationType(int[].class)); assertEquals(TypeDetector.SER_LONG_ARRAY, td.findSerializationType(long[].class)); assertEquals(TypeDetector.SER_BOOLEAN_ARRAY, td.findSerializationType(boolean[].class)); assertEquals(TypeDetector.SER_OBJECT_ARRAY, td.findSerializationType(Object[].class)); assertEquals(TypeDetector.SER_CHARACTER_SEQUENCE, td.findSerializationType(StringBuffer.class)); assertEquals(TypeDetector.SER_COLLECTION, td.findSerializationType(LinkedHashSet.class)); assertEquals(TypeDetector.SER_LIST, td.findSerializationType(ArrayList.class)); assertEquals(TypeDetector.SER_NUMBER_INTEGER, td.findSerializationType(Integer.class)); assertEquals(TypeDetector.SER_NUMBER_INTEGER, td.findSerializationType(Integer.TYPE)); // more specific types assertEquals(TypeDetector.SER_CALENDAR, td.findSerializationType(Calendar.class)); assertEquals(TypeDetector.SER_CALENDAR, td.findSerializationType(GregorianCalendar.class)); assertEquals(TypeDetector.SER_DATE, td.findSerializationType(new GregorianCalendar().getTime().getClass())); assertEquals(TypeDetector.SER_UUID, td.findSerializationType(UUID.class)); } } jackson-jr-jackson-jr-parent-2.9.4/jr-retrofit2/000077500000000000000000000000001323200335100214365ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-retrofit2/pom.xml000066400000000000000000000041551323200335100227600ustar00rootroot00000000000000 4.0.0 com.fasterxml.jackson.jr jackson-jr-parent 2.9.4 jackson-jr-retrofit2 bundle Basic provider implementation for Retrofit 2 library ${project.groupId}.retrofit2 com.fasterxml.jackson.jr jackson-jr-objects ${project.version} com.squareup.retrofit2 retrofit 2.0.0 com.squareup.okhttp3 okhttp 3.2.0 org.apache.maven.plugins maven-javadoc-plugin ${version.plugin.javadoc} http://docs.oracle.com/javase/7/docs/api/ org.apache.maven.plugins maven-surefire-plugin ${surefire.redirectTestOutputToFile} **/failing/*.java jackson-jr-jackson-jr-parent-2.9.4/jr-retrofit2/src/000077500000000000000000000000001323200335100222255ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-retrofit2/src/main/000077500000000000000000000000001323200335100231515ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-retrofit2/src/main/java/000077500000000000000000000000001323200335100240725ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-retrofit2/src/main/java/com/000077500000000000000000000000001323200335100246505ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-retrofit2/src/main/java/com/fasterxml/000077500000000000000000000000001323200335100266555ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-retrofit2/src/main/java/com/fasterxml/jackson/000077500000000000000000000000001323200335100303055ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-retrofit2/src/main/java/com/fasterxml/jackson/jr/000077500000000000000000000000001323200335100307205ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-retrofit2/src/main/java/com/fasterxml/jackson/jr/retrofit2/000077500000000000000000000000001323200335100326405ustar00rootroot00000000000000JacksonJrConverter.java000066400000000000000000000025671323200335100372120ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-retrofit2/src/main/java/com/fasterxml/jackson/jr/retrofit2package com.fasterxml.jackson.jr.retrofit2; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import com.fasterxml.jackson.jr.ob.JSON; import okhttp3.RequestBody; import okhttp3.ResponseBody; import retrofit2.Converter; import retrofit2.Retrofit; public class JacksonJrConverter extends Converter.Factory { protected final JSON _jr; protected final Class _type; public JacksonJrConverter(Class tClass) { this(JSON.std, tClass); } public JacksonJrConverter(JSON jr, Class t) { super(); _jr = jr; _type = t; } @Override public Converter responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { super.responseBodyConverter(type, annotations, retrofit); //if same as class type return as class, otherwise, return as list if (_type == type) { return new JacksonJrResponseConverter(_jr, _type); } return new JacksonJrResponseArrayConverter(_jr, _type); } @Override public Converter requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { super.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit); return new JacksonJrRequestBodyConverter(_jr); } } JacksonJrRequestBodyConverter.java000066400000000000000000000014301323200335100413650ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-retrofit2/src/main/java/com/fasterxml/jackson/jr/retrofit2package com.fasterxml.jackson.jr.retrofit2; import java.io.IOException; import okhttp3.MediaType; import okhttp3.RequestBody; import retrofit2.Converter; import com.fasterxml.jackson.jr.ob.JSON; /** * Created by Gulajava Ministudio on 11/18/15. */ public class JacksonJrRequestBodyConverter implements Converter { private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8"); protected static final String PROTOCOL_CHARSET = "utf-8"; protected final JSON _jr; public JacksonJrRequestBodyConverter(JSON jr) { _jr = jr; } @Override public RequestBody convert(T value) throws IOException { byte[] bytes = _jr.asBytes(value); return RequestBody.create(MEDIA_TYPE, bytes); } } JacksonJrResponseArrayConverter.java000066400000000000000000000011521323200335100417150ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-retrofit2/src/main/java/com/fasterxml/jackson/jr/retrofit2package com.fasterxml.jackson.jr.retrofit2; import java.io.IOException; import java.util.List; import com.fasterxml.jackson.jr.ob.JSON; import okhttp3.ResponseBody; import retrofit2.Converter; public class JacksonJrResponseArrayConverter implements Converter> { protected final JSON _jr; protected final Class _type; public JacksonJrResponseArrayConverter(JSON jr, Class type) { _jr = jr; _type = type; } @Override public List convert(ResponseBody value) throws IOException { return _jr.listOfFrom(_type, value.bytes()); } } JacksonJrResponseConverter.java000066400000000000000000000010651323200335100407210ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-retrofit2/src/main/java/com/fasterxml/jackson/jr/retrofit2package com.fasterxml.jackson.jr.retrofit2; import com.fasterxml.jackson.jr.ob.JSON; import okhttp3.ResponseBody; import java.io.IOException; import retrofit2.Converter; public class JacksonJrResponseConverter implements Converter { protected final JSON _jr; protected final Class _type; public JacksonJrResponseConverter(JSON jr, Class t) { _jr = jr; _type = t; } @Override public T convert(ResponseBody value) throws IOException { return _jr.beanFrom(_type, value.bytes()); } } jackson-jr-jackson-jr-parent-2.9.4/jr-stree/000077500000000000000000000000001323200335100206405ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/README.md000066400000000000000000000014561323200335100221250ustar00rootroot00000000000000## Overview This package is a very simple `TreeCodec` implementation, which allows pluggability with the main `jr-objects` package, specifically for `JSON` object: ```java JSON json = JSON.std.with(new JacksonJrsTreeCodec()); TreeNode root = json.treeFrom(jsonContent); // access content using `get`, `path` and `at` methods ``` As implementation this is meant as minimal package that is mostly useful for reading JSON content as tree and simple traversal, as well as for passing resulting trees to other processing components. Nodes are immutable which is useful for some use (caching), and less useful for others. While it is possible to manually construct trees by directly constructing `JrsObject` (and other instances), it is likely more convenient to use Composer style construction for JSON generation. jackson-jr-jackson-jr-parent-2.9.4/jr-stree/pom.xml000066400000000000000000000045051323200335100221610ustar00rootroot00000000000000 4.0.0 com.fasterxml.jackson.jr jackson-jr-parent 2.9.4 jackson-jr-stree bundle Simple immutable (read-only) tree model that builds directly on jackson-core (streaming), has no other dependencies. https://github.com/FasterXML/jackson-jr com/fasterxml/jackson/jr/stree ${project.groupId}.stree ${basedir}/src/main/java/${packageVersion.dir}/PackageVersion.java.in ${generatedSourcesDir}/${packageVersion.dir}/PackageVersion.java com.fasterxml.jackson.core jackson-core com.fasterxml.jackson.jr jackson-jr-objects ${project.version} test com.google.code.maven-replacer-plugin replacer process-packageVersion generate-sources org.apache.maven.plugins maven-surefire-plugin ${surefire.redirectTestOutputToFile} **/failing/*.java jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/000077500000000000000000000000001323200335100214275ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/000077500000000000000000000000001323200335100223535ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/000077500000000000000000000000001323200335100232745ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/com/000077500000000000000000000000001323200335100240525ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/com/fasterxml/000077500000000000000000000000001323200335100260575ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/com/fasterxml/jackson/000077500000000000000000000000001323200335100275075ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/com/fasterxml/jackson/jr/000077500000000000000000000000001323200335100301225ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/000077500000000000000000000000001323200335100312445ustar00rootroot00000000000000JacksonJrsTreeCodec.java000066400000000000000000000105361323200335100356620ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/com/fasterxml/jackson/jr/streepackage com.fasterxml.jackson.jr.stree; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.*; /** * {@link TreeCodec} implementation that can build "simple", immutable * (read-only) trees out of JSON: these are represented as subtypes * of {@link JrsValue} ("Jrs" from "jackson JR Simple"). */ public class JacksonJrsTreeCodec extends TreeCodec { public static JrsMissing MISSING = JrsMissing.instance; public static final JacksonJrsTreeCodec SINGLETON = new JacksonJrsTreeCodec(); protected ObjectCodec _objectCodec; public JacksonJrsTreeCodec() { this(null); } public JacksonJrsTreeCodec(ObjectCodec codec) { _objectCodec = codec; } @SuppressWarnings("unchecked") @Override public T readTree(JsonParser p) throws IOException { return (T) nodeFrom(p); } private JrsValue nodeFrom(JsonParser p) throws IOException { int tokenId = p.hasCurrentToken() ? p.getCurrentTokenId() : p.nextToken().id(); switch (tokenId) { case JsonTokenId.ID_TRUE: return JrsBoolean.TRUE; case JsonTokenId.ID_FALSE: return JrsBoolean.FALSE; case JsonTokenId.ID_NUMBER_INT: case JsonTokenId.ID_NUMBER_FLOAT: return new JrsNumber(p.getNumberValue()); case JsonTokenId.ID_STRING: return new JrsString(p.getText()); case JsonTokenId.ID_START_ARRAY: { List values = _list(); while (p.nextToken() != JsonToken.END_ARRAY) { values.add(nodeFrom(p)); } return new JrsArray(values); } case JsonTokenId.ID_START_OBJECT: { Map values = _map(); while (p.nextToken() != JsonToken.END_OBJECT) { final String currentName = p.getCurrentName(); p.nextToken(); values.put(currentName, nodeFrom(p)); } return new JrsObject(values); } case JsonTokenId.ID_EMBEDDED_OBJECT: // 07-Jan-2016, tatu: won't happen with JSON, but other types like Smile // may produce binary data or such return new JrsEmbeddedObject(p.getEmbeddedObject()); case JsonTokenId.ID_NULL: // 07-Jan-2016, tatu: ... or should we have NullNode too? return null; default: } throw new UnsupportedOperationException("Unsupported token id "+tokenId+" ("+p.getCurrentToken()+")"); } @Override public void writeTree(JsonGenerator g, TreeNode treeNode) throws IOException { if (treeNode == null) { g.writeNull(); } else { ((JrsValue) treeNode).write(g, this); } } @Override public TreeNode createArrayNode() { return new JrsArray(_list()); } @Override public TreeNode createObjectNode() { return new JrsObject(_map()); } @Override public JsonParser treeAsTokens(TreeNode node) { return ((JrsValue) node).traverse(_objectCodec); } /* /********************************************************************** /* Extended API /********************************************************************** */ public TreeNode missingNode() { return JrsMissing.instance; } /** * @since 2.8 */ public JrsBoolean booleanNode(boolean state) { return state? JrsBoolean.TRUE : JrsBoolean.FALSE; } /** * @since 2.8 */ public JrsString stringNode(String text) { if (text == null) { text = ""; } return new JrsString(text); } /** * @since 2.8 */ public JrsNumber numberNode(Number nr) { if (nr == null) { throw new NullPointerException(); } return new JrsNumber(nr); } /* /********************************************************************** /* Internal methods /********************************************************************** */ protected List _list() { return new ArrayList(); } protected Map _map() { return new LinkedHashMap(); } } JrsArray.java000066400000000000000000000050041323200335100335640ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/com/fasterxml/jackson/jr/streepackage com.fasterxml.jackson.jr.stree; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonPointer; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.core.TreeNode; import static com.fasterxml.jackson.core.JsonToken.START_ARRAY; public class JrsArray extends JrsValue { private final List _values; public JrsArray() { _values = Collections.emptyList(); } public JrsArray(List v) { _values = v; } @Override public JsonToken asToken() { return START_ARRAY; } @Override public int size() { return _values.size(); } @Override public boolean isValueNode() { return false; } @Override public boolean isContainerNode() { return true; } @Override public boolean isArray() { return true; } @Override public JrsValue get(int i) { return ((0 <= i) && (i < _values.size())) ? _values.get(i) : null; } @Override public TreeNode get(String s) { return null; } @Override public JrsValue path(int i){ return ((0 <= i) && (i < _values.size())) ? _values.get(i) : JrsMissing.instance(); } @Override public TreeNode path(String s) { return JrsMissing.instance(); } @Override protected JrsValue _at(JsonPointer ptr) { // fine to return `null`; caller converts to "missing": return get(ptr.getMatchingIndex()); } /* /********************************************************************** /* Extended API /********************************************************************** */ public Iterator elements() { if (_values.isEmpty()) { // fine, nothing that could be removed anyway return _values.iterator(); } // ensure caller can not modify values this way return Collections.unmodifiableList(_values).iterator(); } /* /********************************************************************** /* Abstract methods /********************************************************************** */ @Override protected void write(JsonGenerator g, JacksonJrsTreeCodec codec) throws IOException { g.writeStartArray(); for (int i = 0, end = _values.size(); i < end; ++i) { codec.writeTree(g, _values.get(i)); } g.writeEndArray(); } } JrsBoolean.java000066400000000000000000000024311323200335100340660ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/com/fasterxml/jackson/jr/streepackage com.fasterxml.jackson.jr.stree; import java.io.IOException; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonToken; public class JrsBoolean extends JrsValue.Scalar { public static JrsBoolean TRUE = new JrsBoolean(true, JsonToken.VALUE_TRUE); public static JrsBoolean FALSE = new JrsBoolean(false, JsonToken.VALUE_FALSE); private final boolean _value; private final JsonToken _token; private JrsBoolean(boolean v, JsonToken t) { _value = v; _token = t; } @Override public JsonToken asToken() { return _token; } @Override public String asText() { return _value ? "true" : "false"; } /* /********************************************************************** /* Extended API /********************************************************************** */ public boolean booleanValue() { return _value; } /* /********************************************************************** /* Abstract methods /********************************************************************** */ @Override protected void write(JsonGenerator g, JacksonJrsTreeCodec codec) throws IOException { g.writeBoolean(_value); } } JrsEmbeddedObject.java000066400000000000000000000026411323200335100353320ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/com/fasterxml/jackson/jr/streepackage com.fasterxml.jackson.jr.stree; import java.io.IOException; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonToken; /** * Container for opaque embedded Java objects, exposed by some non-JSON * backends: for example, binary formats would expose binary data natively * as such tokens. */ public class JrsEmbeddedObject extends JrsValue.Scalar { protected final Object _value; public JrsEmbeddedObject(Object v) { _value = v; } @Override public JsonToken asToken() { return JsonToken.VALUE_EMBEDDED_OBJECT; } @Override public String asText() { return null; } /* /********************************************************************** /* Extended API /********************************************************************** */ public Object embeddedValue() { return _value; } /* /********************************************************************** /* Abstract methods /********************************************************************** */ @Override protected void write(JsonGenerator g, JacksonJrsTreeCodec codec) throws IOException { if (_value == null) { g.writeNull(); } else if (_value instanceof byte[]) { g.writeBinary((byte[]) _value); } else { g.writeObject(_value); } } } JrsMissing.java000066400000000000000000000040201323200335100341140ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/com/fasterxml/jackson/jr/streepackage com.fasterxml.jackson.jr.stree; import java.io.IOException; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonPointer; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.core.TreeNode; /** * Virtual node used instead of `null`, when an operation does not match an * actual existing node; this can significantly simplify handling when no * null checks are needed. */ public final class JrsMissing extends JrsValue { final static JrsMissing instance = new JrsMissing(); public final static JrsMissing instance() { return instance; } @Override public JsonToken asToken() { return JsonToken.NOT_AVAILABLE; } @Override public boolean isValueNode() { return false; } @Override public boolean isContainerNode() { return false; } @Override public boolean isMissingNode() { return true; } @Override protected JrsValue _at(JsonPointer ptr) { return this; } @Override public int size() { return 0; } @Override public TreeNode get(String s) { return null; } @Override public TreeNode get(int i) { return null; } @Override public TreeNode path(String s) { return this; } @Override public TreeNode path(int i) { return this; } @Override public boolean equals(Object o) { return (o == this); } @Override public String toString() { // toString() should never return null return ""; } @Override public int hashCode() { return 1; } /* /********************************************************************** /* Abstract methods /********************************************************************** */ @Override protected void write(JsonGenerator g, JacksonJrsTreeCodec codec) throws IOException { // not 100% sure what to do... g.writeNull(); } } JrsNumber.java000066400000000000000000000103121323200335100337340ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/com/fasterxml/jackson/jr/streepackage com.fasterxml.jackson.jr.stree; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Collections; import java.util.HashMap; import java.util.Map; import static com.fasterxml.jackson.core.JsonToken.VALUE_NUMBER_FLOAT; import static com.fasterxml.jackson.core.JsonToken.VALUE_NUMBER_INT; public class JrsNumber extends JrsValue.Scalar { private static final Map, JsonParser.NumberType> NUMBER_TYPES; static { final Map, JsonParser.NumberType> numberTypes = new HashMap, JsonParser.NumberType>(); numberTypes.put(Byte.class, JsonParser.NumberType.INT); numberTypes.put(Short.class, JsonParser.NumberType.INT); numberTypes.put(Integer.class, JsonParser.NumberType.INT); numberTypes.put(Long.class, JsonParser.NumberType.LONG); numberTypes.put(BigInteger.class, JsonParser.NumberType.BIG_INTEGER); numberTypes.put(Float.class, JsonParser.NumberType.FLOAT); numberTypes.put(Double.class, JsonParser.NumberType.DOUBLE); numberTypes.put(BigDecimal.class, JsonParser.NumberType.BIG_DECIMAL); NUMBER_TYPES = Collections.unmodifiableMap(numberTypes); } private final Number _value; private final JsonParser.NumberType _numberType; public JrsNumber(Number value) { _value = value; _numberType = NUMBER_TYPES.get(value.getClass()); if (_numberType == null) { throw new IllegalArgumentException("Unsupported Number type: "+value.getClass().getName()); } } @Override public boolean isNumber() { return true; } public Number getValue() { return _value; } @Override public JsonToken asToken() { switch (numberType()) { case BIG_DECIMAL: case DOUBLE: case FLOAT: return VALUE_NUMBER_FLOAT; default: return VALUE_NUMBER_INT; } } @Override public String asText() { return String.valueOf(_value); } @Override public JsonParser.NumberType numberType() { return _numberType; } /* /********************************************************************** /* Extended API /********************************************************************** */ public BigInteger asBigInteger() throws IOException { if (_value instanceof BigInteger) { return (BigInteger) _value; } if (_value instanceof BigDecimal) { BigDecimal dec = (BigDecimal) _value; return dec.toBigInteger(); } return BigInteger.valueOf(_value.longValue()); } public BigDecimal asBigDecimal() throws IOException { if (_value instanceof BigDecimal) { return (BigDecimal) _value; } if (_value instanceof BigInteger) { return new BigDecimal((BigInteger) _value); } if ((_value instanceof Double) || (_value instanceof Float)) { return new BigDecimal(_value.doubleValue()); } return new BigDecimal(_value.longValue()); } /* /********************************************************************** /* Abstract methods /********************************************************************** */ @Override protected void write(JsonGenerator g, JacksonJrsTreeCodec codec) throws IOException { switch (numberType()) { case INT: g.writeNumber(_value.intValue()); break; case LONG: g.writeNumber(_value.longValue()); break; case BIG_INTEGER: g.writeNumber((BigInteger) _value); break; case FLOAT: g.writeNumber(_value.floatValue()); break; case BIG_DECIMAL: g.writeNumber((BigDecimal) _value); break; case DOUBLE: default: g.writeNumber(_value.doubleValue()); break; } } } JrsObject.java000066400000000000000000000052641323200335100337240ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/com/fasterxml/jackson/jr/streepackage com.fasterxml.jackson.jr.stree; import java.io.IOException; import java.util.Collections; import java.util.Iterator; import java.util.Map; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonPointer; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.core.TreeNode; public class JrsObject extends JrsValue { private final Map _values; public JrsObject() { this(Collections.emptyMap()); } public JrsObject(Map values) { _values = values; } @Override public JsonToken asToken() { return JsonToken.START_OBJECT; } @Override public int size() { return _values.size(); } @Override public boolean isValueNode() { return false; } @Override public boolean isContainerNode() { return true; } @Override public boolean isObject() { return true; } @Override public Iterator fieldNames() { return _values.keySet().iterator(); } @Override public TreeNode get(int i) { return null; } @Override public JrsValue get(String name) { return _values.get(name); } @Override public TreeNode path(int i) { return JrsMissing.instance(); } @Override public JrsValue path(String name) { JrsValue v = _values.get(name); return (v == null) ? JrsMissing.instance() : v; } @Override protected JrsValue _at(JsonPointer ptr) { String prop = ptr.getMatchingProperty(); // fine to return `null`; caller converts to "missing": return get(prop); } /* /********************************************************************** /* Extended API /********************************************************************** */ public Iterator> fields() { if (_values.isEmpty()) { return _values.entrySet().iterator(); } return _values.entrySet().iterator(); } /* /********************************************************************** /* Abstract methods /********************************************************************** */ @Override protected void write(JsonGenerator g, JacksonJrsTreeCodec codec) throws IOException { g.writeStartObject(); if (!_values.isEmpty()) { for (Map.Entry entry : _values.entrySet()) { g.writeFieldName(entry.getKey()); codec.writeTree(g, entry.getValue()); } } g.writeEndObject(); } } JrsString.java000066400000000000000000000017651323200335100337660ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/com/fasterxml/jackson/jr/streepackage com.fasterxml.jackson.jr.stree; import java.io.IOException; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonToken; import static com.fasterxml.jackson.core.JsonToken.VALUE_STRING; public class JrsString extends JrsValue.Scalar { protected final String _value; public JrsString(String v) { if (v == null) { throw new IllegalArgumentException(); } _value = v; } public String getValue() { return _value; } @Override public JsonToken asToken() { return VALUE_STRING; } @Override public String asText() { return _value; } /* /********************************************************************** /* Abstract methods /********************************************************************** */ @Override protected void write(JsonGenerator g, JacksonJrsTreeCodec codec) throws IOException { g.writeString(_value); } } JrsValue.java000066400000000000000000000101231323200335100335600ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/com/fasterxml/jackson/jr/streepackage com.fasterxml.jackson.jr.stree; import java.io.IOException; import java.util.Iterator; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonPointer; import com.fasterxml.jackson.core.ObjectCodec; import com.fasterxml.jackson.core.TreeNode; import com.fasterxml.jackson.jr.stree.util.JrsTreeTraversingParser; /** * Shared base class for all "simple" node types of Jackson Jr * "simple tree" package; implements {@link TreeNode} and is usable * via matching {@link com.fasterxml.jackson.core.TreeCodec} * implementation (see {@link JacksonJrsTreeCodec}). */ public abstract class JrsValue implements TreeNode { @Override public JsonParser.NumberType numberType() { return null; } @Override public boolean isMissingNode() { return false; } @Override public boolean isArray() { return false; } @Override public boolean isObject() { return false; } @Override public Iterator fieldNames() { return null; } @Override public JrsValue at(JsonPointer ptr) { if (ptr.matches()) { return this; } JrsValue n = _at(ptr); while (true) { if (n == null) { return JrsMissing.instance(); } ptr = ptr.tail(); if (ptr.matches()) { return n; } n = n._at(ptr); } } @Override public JrsValue at(String s) { return at(JsonPointer.compile(s)); } @Override public JsonParser traverse() { return new JrsTreeTraversingParser(this); } @Override public JsonParser traverse(ObjectCodec codec) { return new JrsTreeTraversingParser(this, codec); } /* /********************************************************************** /* Extended API /********************************************************************** */ /** * Method that allows checking whether this value is a JSON number * (integer or floating-point). */ public boolean isNumber() { return false; } /** * Method that may be called on scalar value nodes to get a textual * representation of contents. Returns `null` for structured values * (Arrays, Objects), textual representation for other types. */ public String asText() { return null; } /* /********************************************************************** /* Abstract methods for sub-classes /********************************************************************** */ protected abstract JrsValue _at(JsonPointer ptr); protected abstract void write(JsonGenerator g, JacksonJrsTreeCodec codec) throws IOException; /* /********************************************************************** /* Helper classes /********************************************************************** */ /** * Intermediate base class for non-structured types, other than * {@link JrsMissing}. */ public static abstract class Scalar extends JrsValue { @Override public final boolean isValueNode() { return true; } @Override public final boolean isContainerNode() { return false; } @Override public int size() { return 0; } @Override public TreeNode get(String s) { return null; } @Override public TreeNode get(int i) { return null; } @Override public TreeNode path(String s) { return JrsMissing.instance(); } @Override public TreeNode path(int i) { return JrsMissing.instance(); } @Override protected JrsValue _at(JsonPointer ptr) { // will only allow direct matches, but no traversal through // (base class checks for direct match) return null; } } } PackageVersion.java.in000066400000000000000000000011071323200335100353350ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/com/fasterxml/jackson/jr/streepackage @package@; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.core.Versioned; import com.fasterxml.jackson.core.util.VersionUtil; /** * Automatically generated from PackageVersion.java.in during * packageVersion-generate execution of maven-replacer-plugin in * pom.xml. */ public final class PackageVersion implements Versioned { public final static Version VERSION = VersionUtil.parseVersion( "@projectversion@", "@projectgroupid@", "@projectartifactid@"); @Override public Version version() { return VERSION; } } jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/util/000077500000000000000000000000001323200335100322215ustar00rootroot00000000000000JrsTreeTraversingParser.java000066400000000000000000000251171323200335100376130ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/utilpackage com.fasterxml.jackson.jr.stree.util; import java.io.IOException; import java.io.OutputStream; import java.math.BigDecimal; import java.math.BigInteger; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.base.ParserMinimalBase; import com.fasterxml.jackson.jr.stree.JrsArray; import com.fasterxml.jackson.jr.stree.JrsNumber; import com.fasterxml.jackson.jr.stree.JrsObject; import com.fasterxml.jackson.jr.stree.JrsValue; import com.fasterxml.jackson.jr.stree.PackageVersion; /** * Facade over {@link JrsValue} that implements {@link JsonParser} to allow * accessing contents of JSON tree in alternate form (stream of tokens). * Useful when a streaming source is expected by code, such as data binding * functionality. */ public class JrsTreeTraversingParser extends ParserMinimalBase { /* /********************************************************************** /* Configuration /********************************************************************** */ /** * Optional codec, to allow chaining. */ protected ObjectCodec _objectCodec; /** * Traversal context within tree */ protected JrsValueCursor _nodeCursor; /* /********************************************************************** /* State /********************************************************************** */ /** * Sometimes parser needs to buffer a single look-ahead token; if so, * it'll be stored here. This is currently used for handling */ protected JsonToken _nextToken; /** * Flag needed to handle recursion into contents of child * Array/Object nodes. */ protected boolean _startContainer; /** * Flag that indicates whether parser is closed or not. Gets * set when parser is either closed by explicit call * ({@link #close}) or when end-of-input is reached. */ protected boolean _closed; /* /********************************************************************** /* Life-cycle /********************************************************************** */ public JrsTreeTraversingParser(JrsValue n) { this(n, null); } public JrsTreeTraversingParser(JrsValue n, ObjectCodec codec) { super(0); _objectCodec = codec; if (n.isArray()) { _nextToken = JsonToken.START_ARRAY; _nodeCursor = new JrsValueCursor.ArrayCursor((JrsArray) n, null); } else if (n.isObject()) { _nextToken = JsonToken.START_OBJECT; _nodeCursor = new JrsValueCursor.ObjectCursor((JrsObject) n, null); } else { // value node _nodeCursor = new JrsValueCursor.RootCursor(n, null); } } @Override public void setCodec(ObjectCodec c) { _objectCodec = c; } @Override public ObjectCodec getCodec() { return _objectCodec; } @Override public Version version() { return PackageVersion.VERSION; } /* /********************************************************************** /* Closeable implementation /********************************************************************** */ @Override public void close() throws IOException { if (!_closed) { _closed = true; _nodeCursor = null; _currToken = null; } } /* /********************************************************************** /* Public API, traversal /********************************************************************** */ @Override public JsonToken nextToken() throws IOException { if (_nextToken != null) { _currToken = _nextToken; _nextToken = null; return _currToken; } // are we to descend to a container child? if (_startContainer) { _startContainer = false; // minor optimization: empty containers can be skipped if (!_nodeCursor.currentHasChildren()) { _currToken = (_currToken == JsonToken.START_OBJECT) ? JsonToken.END_OBJECT : JsonToken.END_ARRAY; return _currToken; } _nodeCursor = _nodeCursor.iterateChildren(); _currToken = _nodeCursor.nextToken(); if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { _startContainer = true; } return _currToken; } // No more content? if (_nodeCursor == null) { _closed = true; // if not already set return null; } // Otherwise, next entry from current cursor _currToken = _nodeCursor.nextToken(); if (_currToken != null) { if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { _startContainer = true; } return _currToken; } // null means no more children; need to return end marker _currToken = _nodeCursor.endToken(); _nodeCursor = _nodeCursor.getParent(); return _currToken; } // default works well here: //public JsonToken nextValue() throws IOException @Override public JsonParser skipChildren() throws IOException { if (_currToken == JsonToken.START_OBJECT) { _startContainer = false; _currToken = JsonToken.END_OBJECT; } else if (_currToken == JsonToken.START_ARRAY) { _startContainer = false; _currToken = JsonToken.END_ARRAY; } return this; } @Override public boolean isClosed() { return _closed; } /* /********************************************************** /* Public API, token accessors /********************************************************** */ @Override public String getCurrentName() { return (_nodeCursor == null) ? null : _nodeCursor.getCurrentName(); } @Override public void overrideCurrentName(String name) { if (_nodeCursor != null) { _nodeCursor.overrideCurrentName(name); } } @Override public JsonStreamContext getParsingContext() { return _nodeCursor; } @Override public JsonLocation getTokenLocation() { return JsonLocation.NA; } @Override public JsonLocation getCurrentLocation() { return JsonLocation.NA; } /* /********************************************************** /* Public API, access to textual content /********************************************************** */ @Override public String getText() { if (_closed) { return null; } // need to separate handling a bit... switch (_currToken) { case FIELD_NAME: return _nodeCursor.getCurrentName(); case VALUE_STRING: case VALUE_NUMBER_INT: case VALUE_NUMBER_FLOAT: return currentNode().asText(); // 28-Dec-2015, tatu: Not yet supported: // case VALUE_EMBEDDED_OBJECT: default: return (_currToken == null) ? null : _currToken.asString(); } } @Override public char[] getTextCharacters() throws IOException { return getText().toCharArray(); } @Override public int getTextLength() throws IOException { return getText().length(); } @Override public int getTextOffset() throws IOException { return 0; } @Override public boolean hasTextCharacters() { // generally we do not have efficient access as char[], hence: return false; } /* /********************************************************** /* Public API, typed non-text access /********************************************************** */ //public byte getByteValue() throws IOException @Override public NumberType getNumberType() throws IOException { JrsValue n = currentNumericNode(); return (n == null) ? null : n.numberType(); } @Override public BigInteger getBigIntegerValue() throws IOException { return currentNumericNode().asBigInteger(); } @Override public BigDecimal getDecimalValue() throws IOException { return currentNumericNode().asBigDecimal(); } @Override public double getDoubleValue() throws IOException { return currentNumericValue().doubleValue(); } @Override public float getFloatValue() throws IOException { return (float) currentNumericValue().doubleValue(); } @Override public long getLongValue() throws IOException { return currentNumericValue().longValue(); } @Override public int getIntValue() throws IOException { return currentNumericValue().intValue(); } @Override public Number getNumberValue() throws IOException { return currentNumericValue(); } @Override public Object getEmbeddedObject() { // 28-Dec-2015, tatu: Embedded values ("POJO nodes") not yet supported return null; } /* /********************************************************** /* Public API, typed binary (base64) access /********************************************************** */ @Override public byte[] getBinaryValue(Base64Variant b64variant) throws IOException { // 28-Dec-2015, tatu: Binary nodes not yet supported return null; } @Override public int readBinaryValue(Base64Variant b64variant, OutputStream out) throws IOException { // 28-Dec-2015, tatu: Binary nodes not yet supported return -1; } /* /********************************************************** /* Internal methods /********************************************************** */ protected JrsValue currentNode() { if (_closed || _nodeCursor == null) { return null; } return _nodeCursor.currentNode(); } protected JrsNumber currentNumericNode() throws JsonParseException { JrsValue n = currentNode(); if ((n == null) || !(n instanceof JrsNumber)) { JsonToken t = (n == null) ? null : n.asToken(); throw _constructError("Current token ("+t+") not numeric, can not use numeric value accessors"); } return (JrsNumber) n; } protected Number currentNumericValue() throws JsonParseException { return currentNumericNode().getValue(); } @Override protected void _handleEOF() throws JsonParseException { _throwInternal(); // should never get called } } JrsValueCursor.java000066400000000000000000000153701323200335100357440ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/utilpackage com.fasterxml.jackson.jr.stree.util; import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.jr.stree.JrsArray; import com.fasterxml.jackson.jr.stree.JrsObject; import com.fasterxml.jackson.jr.stree.JrsValue; /** * Helper class used by {@link JrsTreeTraversingParser} to keep track * of current location within traversed JSON tree. */ abstract class JrsValueCursor extends JsonStreamContext { /** * Parent cursor of this cursor, if any; null for root * cursors. */ protected final JrsValueCursor _parent; /** * Current field name */ protected String _currentName; /** * @since 2.5 */ protected java.lang.Object _currentValue; public JrsValueCursor(int contextType, JrsValueCursor p) { super(); _type = contextType; _index = -1; _parent = p; } /* /********************************************************************** /* JsonStreamContext impl /********************************************************************** */ // note: co-variant return type @Override public final JrsValueCursor getParent() { return _parent; } @Override public final String getCurrentName() { return _currentName; } /** * @since 2.0 */ public void overrideCurrentName(String name) { _currentName = name; } @Override public java.lang.Object getCurrentValue() { return _currentValue; } @Override public void setCurrentValue(java.lang.Object v) { _currentValue = v; } /* /********************************************************** /* Extended API /********************************************************** */ public abstract JsonToken nextToken(); public abstract JsonToken nextValue(); public abstract JsonToken endToken(); public abstract JrsValue currentNode(); public abstract boolean currentHasChildren(); /** * Method called to create a new context for iterating all * contents of the current structured value (JSON array or object) */ public final JrsValueCursor iterateChildren() { JrsValue n = currentNode(); if (n == null) throw new IllegalStateException("No current node"); if (n.isArray()) { // false since we have already returned START_ARRAY return new ArrayCursor((JrsArray) n, this); } if (n.isObject()) { return new ObjectCursor((JrsObject) n, this); } throw new IllegalStateException("Current node of type "+n.getClass().getName()); } /* /********************************************************** /* Concrete implementations /********************************************************** */ /** * Context matching root-level value nodes (i.e. anything other * than JSON Object and Array). * Note that context is NOT created for leaf values. */ protected final static class RootCursor extends JrsValueCursor { protected JrsValue _node; protected boolean _done = false; public RootCursor(JrsValue n, JrsValueCursor p) { super(JsonStreamContext.TYPE_ROOT, p); _node = n; } @Override public void overrideCurrentName(String name) { } @Override public JsonToken nextToken() { if (!_done) { _done = true; return _node.asToken(); } _node = null; return null; } @Override public JsonToken nextValue() { return nextToken(); } @Override public JsonToken endToken() { return null; } @Override public JrsValue currentNode() { return _node; } @Override public boolean currentHasChildren() { return false; } } /** * Cursor used for traversing non-empty JSON Array nodes */ protected final static class ArrayCursor extends JrsValueCursor { protected Iterator _contents; protected JrsValue _currentNode; public ArrayCursor(JrsArray n, JrsValueCursor p) { super(JsonStreamContext.TYPE_ARRAY, p); _contents = n.elements(); } @Override public JsonToken nextToken() { if (!_contents.hasNext()) { _currentNode = null; return null; } _currentNode = _contents.next(); return _currentNode.asToken(); } @Override public JsonToken nextValue() { return nextToken(); } @Override public JsonToken endToken() { return JsonToken.END_ARRAY; } @Override public JrsValue currentNode() { return _currentNode; } @Override public boolean currentHasChildren() { // note: ONLY to be called for container nodes return currentNode().size() > 0; } } /** * Cursor used for traversing non-empty JSON Object nodes */ protected final static class ObjectCursor extends JrsValueCursor { protected Iterator> _contents; protected Map.Entry _current; protected boolean _needEntry; public ObjectCursor(JrsValue n, JrsValueCursor p) { super(JsonStreamContext.TYPE_OBJECT, p); _contents = ((JrsObject) n).fields(); _needEntry = true; } @Override public JsonToken nextToken() { // Need a new entry? if (_needEntry) { if (!_contents.hasNext()) { _currentName = null; _current = null; return null; } _needEntry = false; _current = _contents.next(); _currentName = (_current == null) ? null : _current.getKey(); return JsonToken.FIELD_NAME; } _needEntry = true; return _current.getValue().asToken(); } @Override public JsonToken nextValue() { JsonToken t = nextToken(); if (t == JsonToken.FIELD_NAME) { t = nextToken(); } return t; } @Override public JsonToken endToken() { return JsonToken.END_OBJECT; } @Override public JrsValue currentNode() { return (_current == null) ? null : _current.getValue(); } @Override public boolean currentHasChildren() { // note: ONLY to be called for container nodes return currentNode().size() > 0; } } } jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/test/000077500000000000000000000000001323200335100224065ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/test/java/000077500000000000000000000000001323200335100233275ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/test/java/com/000077500000000000000000000000001323200335100241055ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/test/java/com/fasterxml/000077500000000000000000000000001323200335100261125ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/test/java/com/fasterxml/jackson/000077500000000000000000000000001323200335100275425ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/test/java/com/fasterxml/jackson/jr/000077500000000000000000000000001323200335100301555ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/test/java/com/fasterxml/jackson/jr/stree/000077500000000000000000000000001323200335100312775ustar00rootroot00000000000000CreateNodesTest.java000066400000000000000000000014411323200335100351170ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/test/java/com/fasterxml/jackson/jr/streepackage com.fasterxml.jackson.jr.stree; import com.fasterxml.jackson.jr.ob.JSON; /** * Trivial tests for wiring; not particularly useful as STree instances are immutable * so while Array/Object nodes may be created, they will be empty and can not * really be changed. */ public class CreateNodesTest extends TestBase { private final JSON treeJSON = JSON.std.with(new JacksonJrsTreeCodec()); public void testCreateArrayNode() throws Exception { JrsArray node = treeJSON.createArrayNode(); assertNotNull(node); assertEquals(0, node.size()); } public void testCreateObjectNode() throws Exception { JrsObject node = treeJSON.createObjectNode(); assertNotNull(node); assertEquals(0, node.size()); } } ReadViaCodecTest.java000066400000000000000000000056621323200335100352050ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/test/java/com/fasterxml/jackson/jr/streepackage com.fasterxml.jackson.jr.stree; import java.io.StringWriter; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.TreeCodec; import com.fasterxml.jackson.core.TreeNode; /** * Tests for reading content directly using codec, and not * through JSON */ public class ReadViaCodecTest extends TestBase { private final TreeCodec TREE_CODEC = new JacksonJrsTreeCodec(); public void testSimpleList() throws Exception { final String INPUT = "[true,\"abc\"]"; TreeNode node = TREE_CODEC.readTree(_factory.createParser(INPUT)); assertTrue(node instanceof JrsArray); assertEquals(2, node.size()); // actually, verify with write... final StringWriter writer = new StringWriter(); final JsonGenerator g = _factory.createGenerator(writer); TREE_CODEC.writeTree(g, node); g.close(); assertEquals(INPUT, writer.toString()); } public void testSimpleMap() throws Exception { final String INPUT = "{\"a\":1,\"b\":true,\"c\":3}"; TreeNode node = TREE_CODEC.readTree(_factory.createParser(INPUT)); assertTrue(node instanceof JrsObject); assertEquals(3, node.size()); // actually, verify with write... final StringWriter writer = new StringWriter(); final JsonGenerator g = _factory.createGenerator(writer); TREE_CODEC.writeTree(g, node); g.close(); assertEquals(INPUT, writer.toString()); } public void testSimpleMixed() throws Exception { final String INPUT = "{\"a\":[1,2,{\"b\":true},3],\"c\":3}"; TreeNode node = TREE_CODEC.readTree(_factory.createParser(INPUT)); assertTrue(node instanceof JrsObject); assertEquals(2, node.size()); TreeNode list = node.get("a"); assertTrue(list instanceof JrsArray); // actually, verify with write... final StringWriter writer = new StringWriter(); final JsonGenerator g = _factory.createGenerator(writer); TREE_CODEC.writeTree(g, node); g.close(); assertEquals(INPUT, writer.toString()); } public void testSimpleJsonPointer() throws Exception { final String INPUT = "{\"a\":[1,2,{\"b\":true},3],\"c\":3}"; TreeNode n; JrsValue v; TreeNode node = TREE_CODEC.readTree(_factory.createParser(INPUT)); n = node.at("/a/1"); assertNotNull(n); v = (JrsValue) n; assertTrue(v.isNumber()); assertEquals(Integer.valueOf(2), ((JrsNumber) v).getValue()); n = node.at("/a/2/b"); assertNotNull(n); v = (JrsValue) n; assertTrue(v instanceof JrsBoolean); assertTrue(((JrsBoolean) v).booleanValue()); n = node.at("/a/7"); assertNotNull(n); assertTrue(n.isMissingNode()); n = node.at("/a/2/c"); assertNotNull(n); assertTrue(n.isMissingNode()); } } ReadViaJSONTest.java000066400000000000000000000041751323200335100347370ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/test/java/com/fasterxml/jackson/jr/streepackage com.fasterxml.jackson.jr.stree; import java.io.StringWriter; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.jr.ob.JSON; /** * Tests for reading content using {@link JSON} with proper * codec registration */ public class ReadViaJSONTest extends TestBase { private final TreeCodec TREE_CODEC = new JacksonJrsTreeCodec(); private final JSON treeJSON = JSON.std.with(TREE_CODEC); public void testSimpleList() throws Exception { final String INPUT = "[true,\"abc\"]"; // and then through jr-objects: TreeNode node = treeJSON.treeFrom(INPUT); assertTrue(node instanceof JrsArray); assertEquals(2, node.size()); // actually, verify with write... final StringWriter writer = new StringWriter(); final JsonGenerator g = _factory.createGenerator(writer); TREE_CODEC.writeTree(g, node); g.close(); assertEquals(INPUT, writer.toString()); } public void testSimpleMap() throws Exception { final String INPUT = "{\"a\":1,\"b\":true,\"c\":3}"; TreeNode node = treeJSON.treeFrom(INPUT); assertTrue(node instanceof JrsObject); assertEquals(3, node.size()); // actually, verify with write... final StringWriter writer = new StringWriter(); final JsonGenerator g = _factory.createGenerator(writer); TREE_CODEC.writeTree(g, node); g.close(); assertEquals(INPUT, writer.toString()); } public void testSimpleMixed() throws Exception { final String INPUT = "{\"a\":[1,2,{\"b\":true},3],\"c\":3}"; TreeNode node = treeJSON.treeFrom(INPUT); assertTrue(node instanceof JrsObject); assertEquals(2, node.size()); TreeNode list = node.get("a"); assertTrue(list instanceof JrsArray); // actually, verify with write... final StringWriter writer = new StringWriter(); final JsonGenerator g = _factory.createGenerator(writer); TREE_CODEC.writeTree(g, node); g.close(); assertEquals(INPUT, writer.toString()); } } SimpleTraverseTest.java000066400000000000000000000032261323200335100356730ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/test/java/com/fasterxml/jackson/jr/streepackage com.fasterxml.jackson.jr.stree; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.jr.stree.JacksonJrsTreeCodec; public class SimpleTraverseTest extends TestBase { private final TreeCodec TREE_CODEC = new JacksonJrsTreeCodec(); public void testSimpleObject() throws Exception { final String INPUT = "{\"a\":[1,2,{\"b\":true},3],\"c\":-2}"; TreeNode node = TREE_CODEC.readTree(_factory.createParser(INPUT)); JsonParser p = node.traverse(); assertToken(JsonToken.START_OBJECT, p.nextToken()); assertToken(JsonToken.FIELD_NAME, p.nextToken()); assertEquals("a", p.getCurrentName()); assertToken(JsonToken.START_ARRAY, p.nextToken()); assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); assertEquals(1, p.getIntValue()); assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); assertEquals(2, p.getIntValue()); assertToken(JsonToken.START_OBJECT, p.nextToken()); assertToken(JsonToken.FIELD_NAME, p.nextToken()); assertEquals("b", p.getCurrentName()); assertToken(JsonToken.VALUE_TRUE, p.nextToken()); assertToken(JsonToken.END_OBJECT, p.nextToken()); assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); assertEquals(3, p.getIntValue()); assertToken(JsonToken.END_ARRAY, p.nextToken()); assertToken(JsonToken.FIELD_NAME, p.nextToken()); assertEquals("c", p.getCurrentName()); assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); assertEquals(-2, p.getIntValue()); assertToken(JsonToken.END_OBJECT, p.nextToken()); p.close(); } } TestBase.java000066400000000000000000000023441323200335100336000ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/test/java/com/fasterxml/jackson/jr/streepackage com.fasterxml.jackson.jr.stree; import java.util.Arrays; import com.fasterxml.jackson.core.*; import junit.framework.TestCase; public abstract class TestBase extends TestCase { protected final JsonFactory _factory = new JsonFactory(); protected void assertToken(JsonToken expToken, JsonToken actToken) { if (actToken != expToken) { fail("Expected token "+expToken+", current token "+actToken); } } protected void assertToken(JsonToken expToken, JsonParser jp) { assertToken(expToken, jp.getCurrentToken()); } protected void verifyException(Throwable e, String... matches) { String msg = e.getMessage(); String lmsg = (msg == null) ? "" : msg.toLowerCase(); for (String match : matches) { String lmatch = match.toLowerCase(); if (lmsg.indexOf(lmatch) >= 0) { return; } } fail("Expected an exception with one of substrings ("+Arrays.asList(matches)+"): got one with message \""+msg+"\""); } protected String quote(String str) { return "\"" + str + "\""; } protected String aposToQuotes(String json) { return json.replace("'", "\""); } } WriteViaCodecTest.java000066400000000000000000000045611323200335100354210ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/test/java/com/fasterxml/jackson/jr/streepackage com.fasterxml.jackson.jr.stree; import java.io.IOException; import java.io.StringWriter; import java.util.*; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.TreeCodec; import com.fasterxml.jackson.core.TreeNode; import com.fasterxml.jackson.jr.stree.JacksonJrsTreeCodec; import com.fasterxml.jackson.jr.stree.JrsArray; import com.fasterxml.jackson.jr.stree.JrsBoolean; import com.fasterxml.jackson.jr.stree.JrsNumber; import com.fasterxml.jackson.jr.stree.JrsObject; import com.fasterxml.jackson.jr.stree.JrsString; import com.fasterxml.jackson.jr.stree.JrsValue; public class WriteViaCodecTest extends TestBase { public void testSimpleList() throws Exception { List stuff = new LinkedList(); stuff.add(new JrsString("x")); stuff.add(JrsBoolean.TRUE); stuff.add(new JrsNumber(123)); assertEquals("[\"x\",true,123]", writeTree(new JacksonJrsTreeCodec(), new JrsArray(stuff))); } public void testSimpleMap() throws Exception { Map stuff = new LinkedHashMap(); stuff.put("a", new JrsNumber(15)); stuff.put("b", JrsBoolean.TRUE); stuff.put("c", new JrsString("foobar")); assertEquals("{\"a\":15,\"b\":true,\"c\":\"foobar\"}", writeTree(new JacksonJrsTreeCodec(), new JrsObject(stuff))); } public void testNest() throws Exception { Map stuff = new LinkedHashMap(); List list = new ArrayList(); list.add(new JrsNumber(123)); list.add(new JrsNumber(456)); stuff.put("first", new JrsArray(list)); Map second = new LinkedHashMap(); stuff.put("second", new JrsObject(second)); second.put("foo", new JrsString("bar")); second.put("bar", new JrsArray()); assertEquals("{\"first\":[123,456],\"second\":{\"foo\":\"bar\",\"bar\":[]}}", writeTree(new JacksonJrsTreeCodec(), new JrsObject(stuff))); } protected String writeTree(TreeCodec treeCodec, TreeNode treeNode) throws IOException { StringWriter writer = new StringWriter(); JsonGenerator g = _factory.createGenerator(writer); treeCodec.writeTree(g, treeNode); g.close(); return writer.toString(); } } WriteViaJSONTest.java000066400000000000000000000031311323200335100351450ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/jr-stree/src/test/java/com/fasterxml/jackson/jr/streepackage com.fasterxml.jackson.jr.stree; import java.util.*; import com.fasterxml.jackson.jr.ob.JSON; public class WriteViaJSONTest extends TestBase { private final JSON treeJSON = JSON.std.with(new JacksonJrsTreeCodec()); public void testSimpleList() throws Exception { List stuff = new LinkedList(); stuff.add(new JrsString("x")); stuff.add(JrsBoolean.TRUE); stuff.add(new JrsNumber(123)); assertEquals("[\"x\",true,123]", treeJSON.asString(new JrsArray(stuff))); } public void testSimpleMap() throws Exception { Map stuff = new LinkedHashMap(); stuff.put("a", new JrsNumber(15)); stuff.put("b", JrsBoolean.TRUE); stuff.put("c", new JrsString("foobar")); assertEquals("{\"a\":15,\"b\":true,\"c\":\"foobar\"}", treeJSON.asString(new JrsObject(stuff))); } public void testNest() throws Exception { Map stuff = new LinkedHashMap(); List list = new ArrayList(); list.add(new JrsNumber(123)); list.add(new JrsNumber(456)); stuff.put("first", new JrsArray(list)); Map second = new LinkedHashMap(); stuff.put("second", new JrsObject(second)); second.put("foo", new JrsString("bar")); second.put("bar", new JrsArray()); assertEquals("{\"first\":[123,456],\"second\":{\"foo\":\"bar\",\"bar\":[]}}", treeJSON.asString(new JrsObject(stuff))); } } jackson-jr-jackson-jr-parent-2.9.4/pom.xml000066400000000000000000000040141323200335100204210ustar00rootroot00000000000000 4.0.0 com.fasterxml.jackson jackson-base 2.9.4 com.fasterxml.jackson.jr jackson-jr-parent Parent pom for Jackson jr components 2.9.4 pom Parent pom for Jackson jr components jr-objects jr-retrofit2 jr-stree jr-all https://github.com/FasterXML/jackson-jr scm:git:git@github.com:FasterXML/jackson-jr.git scm:git:git@github.com:FasterXML/jackson-jr.git http://github.com/FasterXML/jackson-jr jackson-jr-parent-2.9.4 UTF-8 1.6 1.6 2.5.3 source junit junit test jackson-jr-jackson-jr-parent-2.9.4/release-notes/000077500000000000000000000000001323200335100216535ustar00rootroot00000000000000jackson-jr-jackson-jr-parent-2.9.4/release-notes/VERSION000066400000000000000000000066131323200335100227310ustar00rootroot00000000000000Project: jackson-jr ------------------------------------------------------------------------ === Releases === ------------------------------------------------------------------------ 2.9.4 (24-Jan-2018) 2.9.3 (09-Dec-2017) 2.9.2 (14-Oct-2017) 2.9.1 (07-Sep-2017) 2.9.0 (30-Jul-2017) No changes since 2.8 2.8.10 (not yet released) #53: `java.io.File` is not a valid source for anyFrom()/mapFrom() (reported by CoreyTeffetalor@github) 2.8.9 (12-Jun-2017) #50: Duplicate key detection does not work (reported by inorick@github) 2.8.8 (05-Apr-2017) 2.8.7 (21-Feb-2017) 2.8.6 (12-Jan-2017) 2.8.5 (14-Nov-2016) No changes since 2.8.4 2.8.4 (14-Oct-2016) #49: ArrayIndexOutOfBoundsException when parsing large Map (reported by Michael J) 2.8.3 (17-Sep-2016) 2.8.2 (30-Aug-2016) 2.8.1 (19-Jul-2016) No changes since 2.8.0 2.8.0 (04-Jul-2016) #26: Allow use of public fields for getting/setting values #43: Add convenience read method for reading trees via `JSON` 2.7.9 (not yet released) 2.7.8 (26-Sep-2016) 2.7.7 (27-Aug-2016) 2.7.6 (23-Jul-2016) No changes since 2.7.5. 2.7.5 (11-Jun-2016) #42: Incorrect `jackson-core` dependency form parent pom leads to inclusion of non-shaded core jar in `jr-all` (reported by Adam V) 2.7.4 (29-Apr-2016) No changes since 2.7.3. 2.7.3 (16-Mar-2016) #37: Update Jackson Jr Retrofit 2 Converter for Retrofit 2.0.0 (contributed by GulajavaMinistudio@github) #38: PRETTY_PRINT_OUTPUT with composer doesn't work (reported by weizhu-us@github) 2.7.2 (26-Feb-2016) 2.7.1 (02-Feb-2016) No changes since 2.7.0 2.7.0 (10-Jan-2016) #28: Remove misspelled `JSON.Feature.USE_IS_SETTERS` #29: Add `JSON.Feature.WRITE_DATES_AS_TIMESTAMP`, enabling of which allows serialization of `java.util.Date` as long (suggested by Giulio P (gpiancastelli@github)) #30: Add initial version of jackson-jr - based Retrofit2 Converter (contributed by GulajavaMinistudio@github) #31: Fix failure writing UUID, URL and URI (reported by Mitsunori K (komamitsu@github)) #34: Add basic read-only (immutable) tree model impementation (stree) 2.6.6 (05-Apr-2016) #40: Cannot read empty or singleton arrays with JSON.arrayOfFrom (reported by Giulio P) 2.6.5 (19-Jan-2015) 2.6.4 (07-Dec-2015) #27: JSON.Feature.READ_JSON_ARRAYS_AS_JAVA_ARRAYS does not work - Minor fix to resolution of self-referential types (fix #28 from java-classmate) 2.6.3 (12-Oct-2015) 2.6.2 (14-Sep-2015) 2.6.1 (09-Aug-2015) No changes since 2.6.0 2.6.0 (19-Jul-2015) #24: String/byte[] composers can not write POJOs (ObjectCodec not linked) - Minor performance optimizations, using new jackson-core 2.6 methods 2.5.3 (24-Apr-2015) 2.5.2 (29-Mar-2015) 2.5.1 (06-Feb-2015) 2.5.0 (01-Jan-2015) No changes since 2.4. 2.4.4 (24-Nov-2014) 2.4.3 (04-Oct-2014) No changes since 2.4.2 2.4.2 (13-Aug-2014) #15: Problem with Number to Long conversions (reported by "gsmiro@github") #16: Error serializing POJO-valued Maps (reported by Zac M (ZacWolf@github)) 2.4.1 (17-Jun-2014) No changes since 2.4.0 2.4.0 (29-May-2014) #9: Support lazily materialized Maps with `JSON.Feature.USE_DEFERRED_MAPS` #11: Replace use of `java.bean.Introspector` since Android SDK doesn't have it. 2.3.3 (10-Apr-2014) No changes, but depends on Jackson 2.3.3 core. 2.3.1 (26-Mar-2014) #6: Support reading of `Enum` values from String representation #8: Handle generic Collection and Map types properly 2.3.0 (17-Mar-2014) The very first publicly available release!